Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
[bpt/emacs.git] / src / process.c
index 3c6fdbb..67052ca 100644 (file)
@@ -1,7 +1,7 @@
 /* Asynchronous subprocess control for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
-                 1996, 1998, 1999, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                1996, 1998, 1999, 2001, 2002, 2003, 2004,
+                2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -33,20 +33,17 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef subprocesses
 
 #include <stdio.h>
-#include <stdlib.h>
-#include <ctype.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>
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#include <grp.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
 #endif
 
 #ifdef HAVE_UNISTD_H
@@ -72,12 +69,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 #endif /* HAVE_SOCKETS */
 
-#if defined(BSD_SYSTEM)
+#if defined(HAVE_SYS_IOCTL_H)
 #include <sys/ioctl.h>
 #if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
 #include <fcntl.h>
 #endif /* HAVE_PTYS and no O_NDELAY */
-#endif /* BSD_SYSTEM */
+#endif /* HAVE_SYS_IOCTL_H */
 
 #ifdef NEED_BSDTTY
 #include <bsdtty.h>
@@ -123,10 +120,14 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "composite.h"
 #include "atimer.h"
 
+#if defined (USE_GTK) || defined (HAVE_GCONF)
+#include "xgselect.h"
+#endif /* defined (USE_GTK) || defined (HAVE_GCONF) */
+
 Lisp_Object Qprocessp;
 Lisp_Object Qrun, Qstop, Qsignal;
 Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
-Lisp_Object Qlocal, Qipv4, Qdatagram;
+Lisp_Object Qlocal, Qipv4, Qdatagram, Qseqpacket;
 Lisp_Object Qreal, Qnetwork, Qserial;
 #ifdef AF_INET6
 Lisp_Object Qipv6;
@@ -153,7 +154,7 @@ extern Lisp_Object QCfilter;
 Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
 Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
 Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem;
+Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
 
 #ifdef HAVE_SOCKETS
 #define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
@@ -181,7 +182,7 @@ Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem;
 
 #include "syswait.h"
 
-extern char *get_operating_system_release ();
+extern char *get_operating_system_release (void);
 
 /* Serial processes require termios or Windows.  */
 #if defined (HAVE_TERMIOS) || defined (WINDOWSNT)
@@ -194,10 +195,6 @@ extern int serial_open (char *port);
 extern void serial_configure (struct Lisp_Process *p, Lisp_Object contact);
 #endif
 
-#ifndef USE_CRT_DLL
-extern int errno;
-#endif
-
 #ifndef HAVE_H_ERRNO
 extern int h_errno;
 #endif
@@ -252,6 +249,10 @@ int update_tick;
 #endif /* DATAGRAM_SOCKETS */
 #endif /* BROKEN_DATAGRAM_SOCKETS */
 
+#if defined HAVE_LOCAL_SOCKETS && defined DATAGRAM_SOCKETS
+# define HAVE_SEQPACKET
+#endif
+
 #if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING)
 #ifdef EMACS_HAS_USECS
 #define ADAPTIVE_READ_BUFFERING
@@ -284,10 +285,11 @@ static Lisp_Object Vprocess_adaptive_read_buffering;
 
 #include "sysselect.h"
 
-static int keyboard_bit_set P_ ((SELECT_TYPE *));
-static void deactivate_process P_ ((Lisp_Object));
-static void status_notify P_ ((struct Lisp_Process *));
-static int read_process_output P_ ((Lisp_Object, int));
+static int keyboard_bit_set (SELECT_TYPE *);
+static void deactivate_process (Lisp_Object);
+static void status_notify (struct Lisp_Process *);
+static int read_process_output (Lisp_Object, 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.  */
@@ -295,16 +297,19 @@ static int read_process_output P_ ((Lisp_Object, int));
 #define POLL_FOR_INPUT
 #endif
 
-static Lisp_Object get_process ();
-static void exec_sentinel ();
+static Lisp_Object get_process (register Lisp_Object name);
+static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
 
-extern EMACS_TIME timer_check ();
 extern int timers_run;
 \f
 /* Mask of bits indicating the descriptors that we wait for input on.  */
 
 static SELECT_TYPE input_wait_mask;
 
+/* Non-zero if keyboard input is on hold, zero otherwise.  */
+
+static int kbd_is_on_hold;
+
 /* Mask that excludes keyboard input descriptor(s).  */
 
 static SELECT_TYPE non_keyboard_wait_mask;
@@ -398,8 +403,7 @@ static char pty_name[24];
 static Lisp_Object status_convert (int);
 
 static void
-update_status (p)
-     struct Lisp_Process *p;
+update_status (struct Lisp_Process *p)
 {
   eassert (p->raw_status_new);
   p->status = status_convert (p->raw_status);
@@ -428,11 +432,7 @@ status_convert (int w)
    and store them individually through the three pointers.  */
 
 static void
-decode_status (l, symbol, code, coredump)
-     Lisp_Object l;
-     Lisp_Object *symbol;
-     int *code;
-     int *coredump;
+decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, int *coredump)
 {
   Lisp_Object tem;
 
@@ -455,8 +455,7 @@ decode_status (l, symbol, code, coredump)
 /* Return a string describing a process status list.  */
 
 static Lisp_Object
-status_message (p)
-     struct Lisp_Process *p;
+status_message (struct Lisp_Process *p)
 {
   Lisp_Object status = p->status;
   Lisp_Object symbol;
@@ -471,10 +470,21 @@ status_message (p)
       synchronize_system_messages_locale ();
       signame = strsignal (code);
       if (signame == 0)
-       signame = "unknown";
-      string = build_string (signame);
+       string = build_string ("unknown");
+      else
+       {
+         int c1, c2;
+
+         string = make_unibyte_string (signame, strlen (signame));
+         if (! NILP (Vlocale_coding_system))
+           string = (code_convert_string_norecord
+                     (string, Vlocale_coding_system, 0));
+         c1 = STRING_CHAR ((char *) SDATA (string));
+         c2 = DOWNCASE (c1);
+         if (c1 != c2)
+           Faset (string, make_number (0), make_number (c2));
+       }
       string2 = build_string (coredump ? " (core dumped)\n" : "\n");
-      SSET (string, 0, DOWNCASE (SREF (string, 0)));
       return concat2 (string, string2);
     }
   else if (EQ (symbol, Qexit))
@@ -507,7 +517,7 @@ status_message (p)
    is left in the variable pty_name.  */
 
 static int
-allocate_pty ()
+allocate_pty (void)
 {
   register int c, i;
   int fd;
@@ -561,7 +571,7 @@ allocate_pty ()
 #ifdef PTY_TTY_NAME_SPRINTF
            PTY_TTY_NAME_SPRINTF
 #else
-            sprintf (pty_name, "/dev/tty%c%x", c, i);
+           sprintf (pty_name, "/dev/tty%c%x", c, i);
 #endif /* no PTY_TTY_NAME_SPRINTF */
            if (access (pty_name, 6) != 0)
              {
@@ -581,8 +591,7 @@ allocate_pty ()
 #endif /* HAVE_PTYS */
 \f
 static Lisp_Object
-make_process (name)
-     Lisp_Object name;
+make_process (Lisp_Object name)
 {
   register Lisp_Object val, tem, name1;
   register struct Lisp_Process *p;
@@ -626,8 +635,7 @@ make_process (name)
 }
 
 static void
-remove_process (proc)
-     register Lisp_Object proc;
+remove_process (register Lisp_Object proc)
 {
   register Lisp_Object pair;
 
@@ -640,8 +648,7 @@ remove_process (proc)
 /* Setup coding systems of PROCESS.  */
 
 void
-setup_process_coding_systems (process)
-     Lisp_Object process;
+setup_process_coding_systems (Lisp_Object process)
 {
   struct Lisp_Process *p = XPROCESS (process);
   int inch = p->infd;
@@ -717,8 +724,7 @@ BUFFER may be a buffer or the name of one.  */)
    current buffer.  */
 
 static Lisp_Object
-get_process (name)
-     register Lisp_Object name;
+get_process (register Lisp_Object name)
 {
   register Lisp_Object proc, obj;
   if (STRINGP (name))
@@ -778,6 +784,7 @@ nil, indicating the current buffer's process.  */)
       p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
       p->tick = ++process_tick;
       status_notify (p);
+      redisplay_preserve_echo_area (13);
     }
   else if (p->infd >= 0)
     {
@@ -809,6 +816,7 @@ nil, indicating the current buffer's process.  */)
            = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
          p->tick = ++process_tick;
          status_notify (p);
+         redisplay_preserve_echo_area (13);
        }
     }
   remove_process (process);
@@ -1126,7 +1134,7 @@ DEFUN ("set-process-query-on-exit-flag",
        2, 2, 0,
        doc: /* Specify if query is needed for PROCESS when Emacs is exited.
 If the second argument FLAG is non-nil, Emacs will query the user before
-exiting if PROCESS is running.  */)
+exiting or killing a buffer if PROCESS is running.  */)
      (process, flag)
      register Lisp_Object process, flag;
 {
@@ -1147,7 +1155,7 @@ DEFUN ("process-query-on-exit-flag",
 }
 
 #ifdef DATAGRAM_SOCKETS
-Lisp_Object Fprocess_datagram_address ();
+Lisp_Object Fprocess_datagram_address (Lisp_Object process);
 #endif
 
 DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
@@ -1221,7 +1229,7 @@ a socket connection.  */)
   return XPROCESS (process)->type;
 }
 #endif
-  
+
 DEFUN ("process-type", Fprocess_type, Sprocess_type, 1, 1, 0,
        doc: /* Return the connection type of PROCESS.
 The value is either the symbol `real', `network', or `serial'.
@@ -1313,8 +1321,7 @@ Returns nil if format of ADDRESS is invalid.  */)
 #endif
 \f
 static Lisp_Object
-list_processes_1 (query_only)
-     Lisp_Object query_only;
+list_processes_1 (Lisp_Object query_only)
 {
   register Lisp_Object tail, tem;
   Lisp_Object proc, minspace, tem1;
@@ -1484,7 +1491,7 @@ list_processes_1 (query_only)
          insert_string (tembuf);
        }
       else if (NETCONN1_P (p))
-        {
+       {
          /* For a local socket, there is no host name,
             so display service instead.  */
          Lisp_Object host = Fplist_get (p->childp, QChost);
@@ -1500,7 +1507,7 @@ list_processes_1 (query_only)
                   (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
                   (STRINGP (host) ? (char *)SDATA (host) : "?"));
          insert_string (tembuf);
-        }
+       }
       else if (SERIALCONN1_P (p))
        {
          Lisp_Object port = Fplist_get (p->childp, QCport);
@@ -1512,7 +1519,7 @@ list_processes_1 (query_only)
            insert_string ("?");
          if (INTEGERP (speed))
            {
-             sprintf (tembuf, " at %d b/s", XINT (speed));
+             sprintf (tembuf, " at %ld b/s", (long) XINT (speed));
              insert_string (tembuf);
            }
          insert_string (")\n");
@@ -1523,6 +1530,8 @@ list_processes_1 (query_only)
          while (1)
            {
              tem1 = Fcar (tem);
+             if (NILP (tem1))
+               break;
              Finsert (1, &tem1);
              tem = Fcdr (tem);
              if (NILP (tem))
@@ -1533,7 +1542,10 @@ list_processes_1 (query_only)
        }
     }
   if (exited)
-    status_notify (NULL);
+    {
+      status_notify (NULL);
+      redisplay_preserve_echo_area (13);
+    }
   return Qnil;
 }
 
@@ -1560,7 +1572,7 @@ DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
 \f
 /* Starting asynchronous inferior processes.  */
 
-static Lisp_Object start_process_unwind ();
+static Lisp_Object start_process_unwind (Lisp_Object proc);
 
 DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
        doc: /* Start a program in a subprocess.  Return the process object for it.
@@ -1572,8 +1584,9 @@ at end of BUFFER, unless you specify an output stream or filter
 function to handle the output.  BUFFER may also be nil, meaning that
 this process is not associated with any buffer.
 
-PROGRAM is the program file name.  It is searched for in PATH.
-Remaining arguments are strings to give program as arguments.
+PROGRAM is the program file name.  It is searched for in PATH.  If
+nil, just associate a pty with the buffer.  Remaining arguments are
+strings to give program as arguments.
 
 If you want to separate standard output from standard error, invoke
 the command through a shell and redirect one of them using the shell
@@ -1627,7 +1640,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
   program = args[2];
 
-  CHECK_STRING (program);
+  if (!NILP (program))
+    CHECK_STRING (program);
 
   proc = make_process (name);
   /* If an error occurs and we can't start the process, we want to
@@ -1673,7 +1687,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        args2[0] = Qstart_process;
        for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
        GCPRO2 (proc, current_dir);
-       coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+       if (!NILP (program))
+         coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
        UNGCPRO;
        if (CONSP (coding_systems))
          val = XCAR (coding_systems);
@@ -1691,7 +1706,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
            args2[0] = Qstart_process;
            for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
            GCPRO2 (proc, current_dir);
-           coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+           if (!NILP (program))
+             coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
            UNGCPRO;
          }
        if (CONSP (coding_systems))
@@ -1702,66 +1718,86 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
     XPROCESS (proc)->encode_coding_system = val;
   }
 
-  new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
 
-  /* If program file name is not absolute, search our path for it.
-     Put the name we will really use in TEM.  */
-  if (!IS_DIRECTORY_SEP (SREF (program, 0))
-      && !(SCHARS (program) > 1
-          && IS_DEVICE_SEP (SREF (program, 1))))
-    {
-      struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  XPROCESS (proc)->decoding_buf = make_uninit_string (0);
+  XPROCESS (proc)->decoding_carryover = 0;
+  XPROCESS (proc)->encoding_buf = make_uninit_string (0);
 
-      tem = Qnil;
-      GCPRO4 (name, program, buffer, current_dir);
-      openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
-      UNGCPRO;
-      if (NILP (tem))
-       report_file_error ("Searching for program", Fcons (program, Qnil));
-      tem = Fexpand_file_name (tem, Qnil);
-    }
-  else
+  XPROCESS (proc)->inherit_coding_system_flag
+    = !(NILP (buffer) || !inherit_process_coding_system);
+
+  if (!NILP (program))
     {
-      if (!NILP (Ffile_directory_p (program)))
-       error ("Specified program for new process is a directory");
-      tem = program;
-    }
+      /* If program file name is not absolute, search our path for it.
+        Put the name we will really use in TEM.  */
+      if (!IS_DIRECTORY_SEP (SREF (program, 0))
+         && !(SCHARS (program) > 1
+              && IS_DEVICE_SEP (SREF (program, 1))))
+       {
+         struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+         tem = Qnil;
+         GCPRO4 (name, program, buffer, current_dir);
+         openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
+         UNGCPRO;
+         if (NILP (tem))
+           report_file_error ("Searching for program", Fcons (program, Qnil));
+         tem = Fexpand_file_name (tem, Qnil);
+       }
+      else
+       {
+         if (!NILP (Ffile_directory_p (program)))
+           error ("Specified program for new process is a directory");
+         tem = program;
+       }
 
-  /* If program file name starts with /: for quoting a magic name,
-     discard that.  */
-  if (SBYTES (tem) > 2 && SREF (tem, 0) == '/'
-      && SREF (tem, 1) == ':')
-    tem = Fsubstring (tem, make_number (2), Qnil);
+      /* If program file name starts with /: for quoting a magic name,
+        discard that.  */
+      if (SBYTES (tem) > 2 && SREF (tem, 0) == '/'
+         && SREF (tem, 1) == ':')
+       tem = Fsubstring (tem, make_number (2), Qnil);
 
-  /* Encode the file name and put it in NEW_ARGV.
-     That's where the child will use it to execute the program.  */
-  tem = ENCODE_FILE (tem);
-  new_argv[0] = SDATA (tem);
+      {
+       struct gcpro gcpro1;
+       GCPRO1 (tem);
 
-  /* Here we encode arguments by the coding system used for sending
-     data to the process.  We don't support using different coding
-     systems for encoding arguments and for encoding data sent to the
-     process.  */
+       /* Encode the file name and put it in NEW_ARGV.
+          That's where the child will use it to execute the program.  */
+       tem = Fcons (ENCODE_FILE (tem), Qnil);
 
-  for (i = 3; i < nargs; i++)
-    {
-      tem = args[i];
-      CHECK_STRING (tem);
-      if (STRING_MULTIBYTE (tem))
-       tem = (code_convert_string_norecord
-              (tem, XPROCESS (proc)->encode_coding_system, 1));
-      new_argv[i - 2] = SDATA (tem);
-    }
-  new_argv[i - 2] = 0;
+       /* Here we encode arguments by the coding system used for sending
+          data to the process.  We don't support using different coding
+          systems for encoding arguments and for encoding data sent to the
+          process.  */
 
-  XPROCESS (proc)->decoding_buf = make_uninit_string (0);
-  XPROCESS (proc)->decoding_carryover = 0;
-  XPROCESS (proc)->encoding_buf = make_uninit_string (0);
+       for (i = 3; i < nargs; i++)
+         {
+           tem = Fcons (args[i], tem);
+           CHECK_STRING (XCAR (tem));
+           if (STRING_MULTIBYTE (XCAR (tem)))
+             XSETCAR (tem,
+                      code_convert_string_norecord
+                      (XCAR (tem), XPROCESS (proc)->encode_coding_system, 1));
+         }
 
-  XPROCESS (proc)->inherit_coding_system_flag
-    = !(NILP (buffer) || !inherit_process_coding_system);
+       UNGCPRO;
+      }
 
-  create_process (proc, (char **) new_argv, current_dir);
+      /* Now that everything is encoded we can collect the strings into
+        NEW_ARGV.  */
+      new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
+      new_argv[nargs - 2] = 0;
+
+      for (i = nargs - 3; i >= 0; i--)
+       {
+         new_argv[i] = SDATA (XCAR (tem));
+         tem = XCDR (tem);
+       }
+
+      create_process (proc, (char **) new_argv, current_dir);
+    }
+  else
+    create_pty (proc);
 
   return unbind_to (count, proc);
 }
@@ -1771,22 +1807,20 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
    an error and the process wasn't started successfully, so we should
    remove it from the process list.  */
 static Lisp_Object
-start_process_unwind (proc)
-     Lisp_Object proc;
+start_process_unwind (Lisp_Object proc)
 {
   if (!PROCESSP (proc))
     abort ();
 
   /* Was PROC started successfully?  */
-  if (XPROCESS (proc)->pid <= 0)
+  if (XPROCESS (proc)->pid == -1)
     remove_process (proc);
 
   return Qnil;
 }
 
 static void
-create_process_1 (timer)
-     struct atimer *timer;
+create_process_1 (struct atimer *timer)
 {
   /* Nothing to do.  */
 }
@@ -1812,10 +1846,7 @@ create_process_sigchld ()
 #endif
 
 void
-create_process (process, new_argv, current_dir)
-     Lisp_Object process;
-     char **new_argv;
-     Lisp_Object current_dir;
+create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 {
   int inchannel, outchannel;
   pid_t pid;
@@ -1823,7 +1854,6 @@ create_process (process, new_argv, current_dir)
 #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
   int wait_child_setup[2];
 #endif
-#ifdef POSIX_SIGNALS
   sigset_t procmask;
   sigset_t blocked;
   struct sigaction sigint_action;
@@ -1831,13 +1861,6 @@ create_process (process, new_argv, current_dir)
 #ifdef AIX
   struct sigaction sighup_action;
 #endif
-#else /* !POSIX_SIGNALS */
-#if 0
-#ifdef SIGCHLD
-  SIGTYPE (*sigchld)();
-#endif
-#endif /* 0 */
-#endif /* !POSIX_SIGNALS */
   /* Use volatile to protect variables from being clobbered by longjmp.  */
   volatile int forkin, forkout;
   volatile int pty_flag = 0;
@@ -1865,12 +1888,6 @@ create_process (process, new_argv, current_dir)
 #endif
       if (forkin < 0)
        report_file_error ("Opening pty", Qnil);
-#if defined (DONT_REOPEN_PTY)
-      /* In the case that vfork is defined as fork, the parent process
-        (Emacs) may send some data before the child process completes
-        tty options setup.  So we setup tty before forking.  */
-      child_setup_tty (forkout);
-#endif /* DONT_REOPEN_PTY */
 #else
       forkin = forkout = -1;
 #endif /* not USG, or USG_SUBTTY_WORKS */
@@ -1948,7 +1965,6 @@ create_process (process, new_argv, current_dir)
 
   /* Delay interrupts until we have a chance to store
      the new fork's pid in its process structure */
-#ifdef POSIX_SIGNALS
   sigemptyset (&blocked);
 #ifdef SIGCHLD
   sigaddset (&blocked, SIGCHLD);
@@ -1965,18 +1981,6 @@ create_process (process, new_argv, current_dir)
 #endif
 #endif /* HAVE_WORKING_VFORK */
   sigprocmask (SIG_BLOCK, &blocked, &procmask);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#if defined (BSD_SYSTEM) || defined (HPUX)
-  sigsetmask (sigmask (SIGCHLD));
-#else /* ordinary USG */
-#if 0
-  sigchld_deferred = 0;
-  sigchld = signal (SIGCHLD, create_process_sigchld);
-#endif
-#endif /* ordinary USG */
-#endif /* SIGCHLD */
-#endif /* !POSIX_SIGNALS */
 
   FD_SET (inchannel, &input_wait_mask);
   FD_SET (inchannel, &non_keyboard_wait_mask);
@@ -2022,7 +2026,7 @@ create_process (process, new_argv, current_dir)
           process_set_signal to fail on SGI when using a pipe.  */
        setsid ();
        /* Make the pty's terminal the controlling terminal.  */
-       if (pty_flag)
+       if (pty_flag && xforkin >= 0)
          {
 #ifdef TIOCSCTTY
            /* We ignore the return value
@@ -2065,8 +2069,11 @@ create_process (process, new_argv, current_dir)
            /* 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);
-           ioctl (j, TIOCNOTTY, 0);
-           emacs_close (j);
+           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
@@ -2127,24 +2134,10 @@ create_process (process, new_argv, current_dir)
        signal (SIGQUIT, SIG_DFL);
 
        /* Stop blocking signals in the child.  */
-#ifdef POSIX_SIGNALS
        sigprocmask (SIG_SETMASK, &procmask, 0);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#if defined (BSD_SYSTEM) || defined (HPUX)
-       sigsetmask (SIGEMPTYMASK);
-#else /* ordinary USG */
-#if 0
-       signal (SIGCHLD, sigchld);
-#endif
-#endif /* ordinary USG */
-#endif /* SIGCHLD */
-#endif /* !POSIX_SIGNALS */
 
-#if !defined (DONT_REOPEN_PTY)
        if (pty_flag)
          child_setup_tty (xforkout);
-#endif /* not DONT_REOPEN_PTY */
 #ifdef WINDOWSNT
        pid = child_setup (xforkin, xforkout, xforkout,
                           new_argv, 1, current_dir);
@@ -2223,7 +2216,6 @@ create_process (process, new_argv, current_dir)
 
   /* Restore the signal state whether vfork succeeded or not.
      (We will signal an error, below, if it failed.)  */
-#ifdef POSIX_SIGNALS
 #ifdef HAVE_WORKING_VFORK
   /* Restore the parent's signal handlers.  */
   sigaction (SIGINT, &sigint_action, 0);
@@ -2234,27 +2226,93 @@ create_process (process, new_argv, current_dir)
 #endif /* HAVE_WORKING_VFORK */
   /* Stop blocking signals in the parent.  */
   sigprocmask (SIG_SETMASK, &procmask, 0);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#if defined (BSD_SYSTEM) || defined (HPUX)
-  sigsetmask (SIGEMPTYMASK);
-#else /* ordinary USG */
-#if 0
-  signal (SIGCHLD, sigchld);
-  /* Now really handle any of these signals
-     that came in during this function.  */
-  if (sigchld_deferred)
-    kill (getpid (), SIGCHLD);
-#endif
-#endif /* ordinary USG */
-#endif /* SIGCHLD */
-#endif /* !POSIX_SIGNALS */
 
   /* Now generate the error if vfork failed.  */
   if (pid < 0)
     report_file_error ("Doing vfork", Qnil);
 }
 
+void
+create_pty (Lisp_Object process)
+{
+  int inchannel, outchannel;
+
+  /* Use volatile to protect variables from being clobbered by longjmp.  */
+  volatile int forkin, forkout;
+  volatile int pty_flag = 0;
+
+  inchannel = outchannel = -1;
+
+#ifdef HAVE_PTYS
+  if (!NILP (Vprocess_connection_type))
+    outchannel = inchannel = allocate_pty ();
+
+  if (inchannel >= 0)
+    {
+#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);
+#if defined (DONT_REOPEN_PTY)
+      /* In the case that vfork is defined as fork, the parent process
+        (Emacs) may send some data before the child process completes
+        tty options setup.  So we setup tty before forking.  */
+      child_setup_tty (forkout);
+#endif /* DONT_REOPEN_PTY */
+#else
+      forkin = forkout = -1;
+#endif /* not USG, or USG_SUBTTY_WORKS */
+      pty_flag = 1;
+    }
+#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.  */
+  chan_process[inchannel] = process;
+  XPROCESS (process)->infd = inchannel;
+  XPROCESS (process)->outfd = outchannel;
+
+  /* Previously we recorded the tty descriptor used in the subprocess.
+     It was only used for getting the foreground tty process, so now
+     we just reopen the device (see emacs_get_tty_pgrp) as this is
+     more portable (see USG_SUBTTY_WORKS above).  */
+
+  XPROCESS (process)->pty_flag = pty_flag;
+  XPROCESS (process)->status = Qrun;
+  setup_process_coding_systems (process);
+
+  FD_SET (inchannel, &input_wait_mask);
+  FD_SET (inchannel, &non_keyboard_wait_mask);
+  if (inchannel > max_process_desc)
+    max_process_desc = inchannel;
+
+  XPROCESS (process)->pid = -2;
+#ifdef HAVE_PTYS
+  if (pty_flag)
+    XPROCESS (process)->tty_name = build_string (pty_name);
+  else
+#endif
+    XPROCESS (process)->tty_name = Qnil;
+}
+
 \f
 #ifdef HAVE_SOCKETS
 
@@ -2262,15 +2320,19 @@ create_process (process, new_argv, current_dir)
    The address family of sa is not included in the result.  */
 
 static Lisp_Object
-conv_sockaddr_to_lisp (sa, len)
-     struct sockaddr *sa;
-     int len;
+conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
 {
   Lisp_Object address;
   int i;
   unsigned char *cp;
   register struct Lisp_Vector *p;
 
+  /* Workaround for a bug in getsockname on BSD: Names bound to
+     sockets in the UNIX domain are inaccessible; getsockname returns
+     a zero length name.  */
+  if (len < OFFSETOF (struct sockaddr, sa_family) + sizeof (sa->sa_family))
+    return empty_unibyte_string;
+
   switch (sa->sa_family)
     {
     case AF_INET:
@@ -2280,14 +2342,14 @@ conv_sockaddr_to_lisp (sa, len)
        address = Fmake_vector (make_number (len), Qnil);
        p = XVECTOR (address);
        p->contents[--len] = make_number (ntohs (sin->sin_port));
-       cp = (unsigned char *)&sin->sin_addr;
+       cp = (unsigned char *) &sin->sin_addr;
        break;
       }
 #ifdef AF_INET6
     case AF_INET6:
       {
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
-       uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
+       uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr;
        len = sizeof (sin6->sin6_addr)/2 + 1;
        address = Fmake_vector (make_number (len), Qnil);
        p = XVECTOR (address);
@@ -2308,11 +2370,11 @@ conv_sockaddr_to_lisp (sa, len)
       }
 #endif
     default:
-      len -= sizeof (sa->sa_family);
+      len -= OFFSETOF (struct sockaddr, sa_family) + sizeof (sa->sa_family);
       address = Fcons (make_number (sa->sa_family),
                       Fmake_vector (make_number (len), Qnil));
       p = XVECTOR (XCDR (address));
-      cp = (unsigned char *) sa + sizeof (sa->sa_family);
+      cp = (unsigned char *) &sa->sa_family + sizeof (sa->sa_family);
       break;
     }
 
@@ -2327,9 +2389,7 @@ conv_sockaddr_to_lisp (sa, len)
 /* Get family and required size for sockaddr structure to hold ADDRESS.  */
 
 static int
-get_lisp_to_sockaddr_size (address, familyp)
-     Lisp_Object address;
-     int *familyp;
+get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
 {
   register struct Lisp_Vector *p;
 
@@ -2374,17 +2434,13 @@ get_lisp_to_sockaddr_size (address, familyp)
    we return after zeroing *SA.  */
 
 static void
-conv_lisp_to_sockaddr (family, address, sa, len)
-     int family;
-     Lisp_Object address;
-     struct sockaddr *sa;
-     int len;
+conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int len)
 {
   register struct Lisp_Vector *p;
   register unsigned char *cp = NULL;
   register int i;
 
-  bzero (sa, len);
+  memset (sa, 0, len);
 
   if (VECTORP (address))
     {
@@ -2413,9 +2469,11 @@ conv_lisp_to_sockaddr (family, address, sa, len)
                ip6[i] = ntohs (j);
              }
          sa->sa_family = family;
+         return;
        }
 #endif
-      return;
+      else
+       return;
     }
   else if (STRINGP (address))
     {
@@ -2487,7 +2545,7 @@ Returns nil upon error setting address, ADDRESS otherwise.  */)
 #endif
 \f
 
-static struct socket_options {
+static const struct socket_options {
   /* The name of this option.  Should be lowercase version of option
      name without SO_ prefix. */
   char *name;
@@ -2533,12 +2591,10 @@ static struct socket_options {
 */
 
 static int
-set_socket_option (s, opt, val)
-     int s;
-     Lisp_Object opt, val;
+set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
 {
   char *name;
-  struct socket_options *sopt;
+  const struct socket_options *sopt;
   int ret = 0;
 
   CHECK_SYMBOL (opt);
@@ -2579,12 +2635,12 @@ set_socket_option (s, opt, val)
        /* This is broken, at least in the Linux 2.4 kernel.
           To unbind, the arg must be a zero integer, not the empty string.
           This should work on all systems.   KFS. 2003-09-23.  */
-       bzero (devname, sizeof devname);
+       memset (devname, 0, sizeof devname);
        if (STRINGP (val))
          {
            char *arg = (char *) SDATA (val);
            int len = min (strlen (arg), IFNAMSIZ);
-           bcopy (arg, devname, len);
+           memcpy (devname, arg, len);
          }
        else if (!NILP (val))
          error ("Bad option value for %s", name);
@@ -2951,7 +3007,7 @@ usage:  (make-serial-process &rest ARGS)  */)
   p->inherit_coding_system_flag
     = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
 
-  Fserial_process_configure(nargs, args);
+  Fserial_process_configure (nargs, args);
 
   specpdl_ptr = specpdl + specpdl_count;
 
@@ -3000,7 +3056,8 @@ compiled with getaddrinfo, a port number can also be specified as a
 string, e.g. "80", as well as an integer.  This is not portable.)
 
 :type TYPE -- TYPE is the type of connection.  The default (nil) is a
-stream type connection, `datagram' creates a datagram type connection.
+stream type connection, `datagram' creates a datagram type connection,
+`seqpacket' creates a reliable datagram connection.
 
 :family FAMILY -- FAMILY is the address (and protocol) family for the
 service specified by HOST and SERVICE.  The default (nil) is to use
@@ -3178,6 +3235,10 @@ usage: (make-network-process &rest ARGS)  */)
 #ifdef DATAGRAM_SOCKETS
   else if (EQ (tem, Qdatagram))
     socktype = SOCK_DGRAM;
+#endif
+#ifdef HAVE_SEQPACKET
+  else if (EQ (tem, Qseqpacket))
+    socktype = SOCK_SEQPACKET;
 #endif
   else
     error ("Unsupported connection type");
@@ -3201,7 +3262,7 @@ usage: (make-network-process &rest ARGS)  */)
   QCaddress = is_server ? QClocal : QCremote;
 
   /* :nowait BOOL */
-  if (!is_server && socktype == SOCK_STREAM
+  if (!is_server && socktype != SOCK_DGRAM
       && (tem = Fplist_get (contact, QCnowait), !NILP (tem)))
     {
 #ifndef NON_BLOCKING_CONNECT
@@ -3268,13 +3329,27 @@ usage: (make-network-process &rest ARGS)  */)
   /* :service SERVICE -- string, integer (port number), or t (random port).  */
   service = Fplist_get (contact, QCservice);
 
+  /* :host HOST -- hostname, ip address, or 'local for localhost.  */
+  host = Fplist_get (contact, QChost);
+  if (!NILP (host))
+    {
+      if (EQ (host, Qlocal))
+       host = build_string ("localhost");
+      CHECK_STRING (host);
+    }
+
 #ifdef HAVE_LOCAL_SOCKETS
   if (family == AF_LOCAL)
     {
-      /* Host is not used.  */
-      host = Qnil;
+      if (!NILP (host))
+       {
+         message (":family local ignores the :host \"%s\" property",
+                  SDATA (host));
+         contact = Fplist_put (contact, QChost, Qnil);
+         host = Qnil;
+       }
       CHECK_STRING (service);
-      bzero (&address_un, sizeof address_un);
+      memset (&address_un, 0, sizeof address_un);
       address_un.sun_family = AF_LOCAL;
       strncpy (address_un.sun_path, SDATA (service), sizeof address_un.sun_path);
       ai.ai_addr = (struct sockaddr *) &address_un;
@@ -3283,20 +3358,11 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif
 
-  /* :host HOST -- hostname, ip address, or 'local for localhost.  */
-  host = Fplist_get (contact, QChost);
-  if (!NILP (host))
-    {
-      if (EQ (host, Qlocal))
-       host = build_string ("localhost");
-      CHECK_STRING (host);
-    }
-
   /* Slow down polling to every ten seconds.
      Some kernels have a bug which causes retrying connect to fail
      after a connect.  Polling can interfere with gethostbyname too.  */
 #ifdef POLL_FOR_INPUT
-  if (socktype == SOCK_STREAM)
+  if (socktype != SOCK_DGRAM)
     {
       record_unwind_protect (unwind_stop_other_atimers, Qnil);
       bind_polling_period (10);
@@ -3339,9 +3405,9 @@ usage: (make-network-process &rest ARGS)  */)
       ret = getaddrinfo (SDATA (host), portstring, &hints, &res);
       if (ret)
 #ifdef HAVE_GAI_STRERROR
-       error ("%s/%s %s", SDATA (host), portstring, gai_strerror(ret));
+       error ("%s/%s %s", SDATA (host), portstring, gai_strerror (ret));
 #else
-        error ("%s/%s getaddrinfo error %d", SDATA (host), portstring, ret);
+       error ("%s/%s getaddrinfo error %d", SDATA (host), portstring, ret);
 #endif
       immediate_quit = 0;
 
@@ -3367,7 +3433,7 @@ usage: (make-network-process &rest ARGS)  */)
       port = svc_info->s_port;
     }
 
-  bzero (&address_in, sizeof address_in);
+  memset (&address_in, 0, sizeof address_in);
   address_in.sin_family = family;
   address_in.sin_addr.s_addr = INADDR_ANY;
   address_in.sin_port = port;
@@ -3391,8 +3457,8 @@ usage: (make-network-process &rest ARGS)  */)
 
       if (host_info_ptr)
        {
-         bcopy (host_info_ptr->h_addr, (char *) &address_in.sin_addr,
-                host_info_ptr->h_length);
+         memcpy (&address_in.sin_addr, host_info_ptr->h_addr,
+                 host_info_ptr->h_length);
          family = host_info_ptr->h_addrtype;
          address_in.sin_family = family;
        }
@@ -3404,8 +3470,8 @@ usage: (make-network-process &rest ARGS)  */)
          if (numeric_addr == -1)
            error ("Unknown host \"%s\"", SDATA (host));
 
-         bcopy ((char *)&numeric_addr, (char *) &address_in.sin_addr,
-                sizeof (address_in.sin_addr));
+         memcpy (&address_in.sin_addr, &numeric_addr,
+                 sizeof (address_in.sin_addr));
        }
 
     }
@@ -3462,7 +3528,7 @@ usage: (make-network-process &rest ARGS)  */)
 
       /* Parse network options in the arg list.
         We simply ignore anything which isn't a known option (including other keywords).
-         An error is signaled if setting a known option fails.  */
+        An error is signaled if setting a known option fails.  */
       for (optn = optbits = 0; optn < nargs-1; optn += 2)
        optbits |= set_socket_option (s, args[optn], args[optn+1]);
 
@@ -3499,7 +3565,7 @@ usage: (make-network-process &rest ARGS)  */)
            }
 #endif
 
-         if (socktype == SOCK_STREAM && listen (s, backlog))
+         if (socktype != SOCK_DGRAM && listen (s, backlog))
            report_file_error ("Cannot listen on server socket", Qnil);
 
          break;
@@ -3508,23 +3574,9 @@ usage: (make-network-process &rest ARGS)  */)
       immediate_quit = 1;
       QUIT;
 
-      /* This turns off all alarm-based interrupts; the
-        bind_polling_period call above doesn't always turn all the
-        short-interval ones off, especially if interrupt_input is
-        set.
-
-        It'd be nice to be able to control the connect timeout
-        though.  Would non-blocking connect calls be portable?
-
-        This used to be conditioned by HAVE_GETADDRINFO.  Why?  */
-
-      turn_on_atimers (0);
-
       ret = connect (s, lres->ai_addr, lres->ai_addrlen);
       xerrno = errno;
 
-      turn_on_atimers (1);
-
       if (ret == 0 || xerrno == EISCONN)
        {
          /* The unwind-protect will be discarded afterwards.
@@ -3544,6 +3596,40 @@ usage: (make-network-process &rest ARGS)  */)
 #endif
 #endif
 
+#ifndef WINDOWSNT
+      if (xerrno == EINTR)
+       {
+         /* Unlike most other syscalls connect() cannot be called
+            again.  (That would return EALREADY.)  The proper way to
+            wait for completion is select(). */
+         int sc, len;
+         SELECT_TYPE fdset;
+       retry_select:
+         FD_ZERO (&fdset);
+         FD_SET (s, &fdset);
+         QUIT;
+         sc = select (s + 1, (SELECT_TYPE *)0, &fdset, (SELECT_TYPE *)0,
+                      (EMACS_TIME *)0);
+         if (sc == -1)
+           {
+             if (errno == EINTR)
+               goto retry_select;
+             else
+               report_file_error ("select failed", Qnil);
+           }
+         eassert (sc > 0);
+
+         len = sizeof xerrno;
+         eassert (FD_ISSET (s, &fdset));
+         if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) == -1)
+           report_file_error ("getsockopt failed", Qnil);
+         if (xerrno)
+           errno = xerrno, report_file_error ("error during connect", Qnil);
+         else
+           break;
+       }
+#endif /* !WINDOWSNT */
+
       immediate_quit = 0;
 
       /* Discard the unwind protect closing S.  */
@@ -3551,8 +3637,10 @@ usage: (make-network-process &rest ARGS)  */)
       emacs_close (s);
       s = -1;
 
+#ifdef WINDOWSNT
       if (xerrno == EINTR)
        goto retry_connect;
+#endif
     }
 
   if (s >= 0)
@@ -3567,7 +3655,7 @@ usage: (make-network-process &rest ARGS)  */)
          if (is_server)
            {
              Lisp_Object remote;
-             bzero (datagram_address[s].sa, lres->ai_addrlen);
+             memset (datagram_address[s].sa, 0, lres->ai_addrlen);
              if (remote = Fplist_get (contact, QCremote), !NILP (remote))
                {
                  int rfamily, rlen;
@@ -3578,7 +3666,7 @@ usage: (make-network-process &rest ARGS)  */)
                }
            }
          else
-           bcopy (lres->ai_addr, datagram_address[s].sa, lres->ai_addrlen);
+           memcpy (datagram_address[s].sa, lres->ai_addr, lres->ai_addrlen);
        }
 #endif
       contact = Fplist_put (contact, QCaddress,
@@ -3590,7 +3678,7 @@ usage: (make-network-process &rest ARGS)  */)
          int len1 = sizeof (sa1);
          if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
            contact = Fplist_put (contact, QClocal,
-                                 conv_sockaddr_to_lisp (&sa1, len1));
+                                 conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1));
        }
 #endif
     }
@@ -3662,7 +3750,7 @@ usage: (make-network-process &rest ARGS)  */)
   p->pid = 0;
   p->infd  = inch;
   p->outfd = outch;
-  if (is_server && socktype == SOCK_STREAM)
+  if (is_server && socktype != SOCK_DGRAM)
     p->status = Qlisten;
 
   /* Make the process marker point into the process buffer (if any).  */
@@ -3816,7 +3904,7 @@ format; see the description of ADDRESS in `make-network-process'.  */)
 
  again:
   ifaces += 25;
-  buf_size = ifaces * sizeof(ifreqs[0]);
+  buf_size = ifaces * sizeof (ifreqs[0]);
   ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size);
   if (!ifreqs)
     {
@@ -3845,7 +3933,7 @@ format; see the description of ADDRESS in `make-network-process'.  */)
       char namebuf[sizeof (ifq->ifr_name) + 1];
       if (ifq->ifr_addr.sa_family != AF_INET)
        continue;
-      bcopy (ifq->ifr_name, namebuf, sizeof (ifq->ifr_name));
+      memcpy (namebuf, ifq->ifr_name, sizeof (ifq->ifr_name));
       namebuf[sizeof (ifq->ifr_name)] = 0;
       res = Fcons (Fcons (build_string (namebuf),
                          conv_sockaddr_to_lisp (&ifq->ifr_addr,
@@ -3861,10 +3949,10 @@ format; see the description of ADDRESS in `make-network-process'.  */)
 
 struct ifflag_def {
   int flag_bit;
-  char *flag_sym;
+  const char *flag_sym;
 };
 
-static struct ifflag_def ifflag_table[] = {
+static const struct ifflag_def ifflag_table[] = {
 #ifdef IFF_UP
   { IFF_UP,            "up" },
 #endif
@@ -3948,7 +4036,7 @@ FLAGS is the current flags of the interface.  */)
 
   CHECK_STRING (ifname);
 
-  bzero (rq.ifr_name, sizeof rq.ifr_name);
+  memset (rq.ifr_name, 0, sizeof rq.ifr_name);
   strncpy (rq.ifr_name, SDATA (ifname), sizeof (rq.ifr_name));
 
   s = socket (AF_INET, SOCK_STREAM, 0);
@@ -3960,7 +4048,7 @@ FLAGS is the current flags of the interface.  */)
   if (ioctl (s, SIOCGIFFLAGS, &rq) == 0)
     {
       int flags = rq.ifr_flags;
-      struct ifflag_def *fp;
+      const struct ifflag_def *fp;
       int fnum;
 
       any++;
@@ -4043,8 +4131,7 @@ FLAGS is the current flags of the interface.  */)
 /* Turn off input and output for process PROC.  */
 
 void
-deactivate_process (proc)
-     Lisp_Object proc;
+deactivate_process (Lisp_Object proc)
 {
   register int inchannel, outchannel;
   register struct Lisp_Process *p = XPROCESS (proc);
@@ -4109,7 +4196,7 @@ deactivate_process (proc)
    to get rid of irrelevant descriptors.  */
 
 void
-close_process_descs ()
+close_process_descs (void)
 {
 #ifndef WINDOWSNT
   int i;
@@ -4137,9 +4224,9 @@ It is read into the process' buffers or given to their filter functions.
 Non-nil arg PROCESS means do not return until some output has been received
 from PROCESS.
 
-Non-nil second arg SECONDS and third arg MILLISEC are number of
-seconds and milliseconds to wait; return after that much time whether
-or not there is input.  If SECONDS is a floating point number,
+Non-nil second arg SECONDS and third arg MILLISEC are number of seconds
+and milliseconds to wait; return after that much time whether or not
+there is any subprocess output.  If SECONDS is a floating point number,
 it specifies a fractional number of seconds to wait.
 The MILLISEC argument is obsolete and should be avoided.
 
@@ -4202,9 +4289,7 @@ Return non-nil if we received any output before the timeout expired.  */)
 static int connect_counter = 0;
 
 static void
-server_accept_connection (server, channel)
-     Lisp_Object server;
-     int channel;
+server_accept_connection (Lisp_Object server, int channel)
 {
   Lisp_Object proc, caller, name, buffer;
   Lisp_Object contact, host, service;
@@ -4281,7 +4366,7 @@ server_accept_connection (server, channel)
        int i;
        args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
        for (i = 0; i < 8; i++)
-         args[i+1] = make_number (ntohs(ip6[i]));
+         args[i+1] = make_number (ntohs (ip6[i]));
        host = Fformat (9, args);
        service = make_number (ntohs (saddr.in.sin_port));
 
@@ -4420,8 +4505,7 @@ server_accept_connection (server, channel)
 static int waiting_for_user_input_p;
 
 static Lisp_Object
-wait_reading_process_output_unwind (data)
-     Lisp_Object data;
+wait_reading_process_output_unwind (Lisp_Object data)
 {
   waiting_for_user_input_p = XINT (data);
   return Qnil;
@@ -4429,12 +4513,12 @@ wait_reading_process_output_unwind (data)
 
 /* This is here so breakpoints can be put on it.  */
 static void
-wait_reading_process_output_1 ()
+wait_reading_process_output_1 (void)
 {
 }
 
 /* Use a wrapper around select to work around a bug in gdb 5.3.
-   Normally, the wrapper is optimzed away by inlining.
+   Normally, the wrapper is optimized away by inlining.
 
    If emacs is stopped inside select, the gdb backtrace doesn't
    show the function which called select, so it is practically
@@ -4442,10 +4526,7 @@ wait_reading_process_output_1 ()
 
 #ifndef select
 static INLINE int
-select_wrapper (n, rfd, wfd, xfd, tmo)
-  int n;
-  SELECT_TYPE *rfd, *wfd, *xfd;
-  EMACS_TIME *tmo;
+select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tmo)
 {
   return select (n, rfd, wfd, xfd, tmo);
 }
@@ -4516,6 +4597,10 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
   FD_ZERO (&Connecting);
 #endif
 
+  if (time_limit == 0 && wait_proc && !NILP (Vinhibit_quit)
+      && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
+    message ("Blocking call to accept-process-output with quit inhibited!!");
+
   /* If wait_proc is a process to watch, set wait_channel accordingly.  */
   if (wait_proc != NULL)
     wait_channel = wait_proc->infd;
@@ -4544,12 +4629,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
        QUIT;
 #ifdef SYNC_INPUT
       else
-        {
-          if (interrupt_input_pending)
-            handle_async_input ();
-          if (pending_atimers)
-            do_pending_atimers ();
-        }
+       process_pending_signals ();
 #endif
 
       /* Exit now if the cell we're waiting for became non-nil.  */
@@ -4647,18 +4727,18 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
       /* If status of something has changed, and no input is
         available, notify the user of the change right away.  After
         this explicit check, we'll let the SIGCHLD handler zap
-        timeout to get our attention.  When Emacs is run
-        interactively, only do this with a nonzero DO_DISPLAY
-        argument, because status_notify triggers redisplay.  */
-      if (update_tick != process_tick
-         && (do_display || noninteractive))
+        timeout to get our attention.  */
+      if (update_tick != process_tick)
        {
          SELECT_TYPE Atemp;
 #ifdef NON_BLOCKING_CONNECT
          SELECT_TYPE Ctemp;
 #endif
 
-         Atemp = input_wait_mask;
+          if (kbd_on_hold_p ())
+            FD_ZERO (&Atemp);
+          else
+            Atemp = input_wait_mask;
          IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask);
 
          EMACS_SET_SECS_USECS (timeout, 0, 0);
@@ -4677,11 +4757,12 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
                 the loop, since timeout has already been zeroed out.  */
              clear_waiting_for_input ();
              status_notify (NULL);
+             if (do_display) redisplay_preserve_echo_area (13);
            }
        }
 
       /* Don't wait for output from a non-running process.  Just
-         read whatever data has already been received.  */
+        read whatever data has already been received.  */
       if (wait_proc && wait_proc->raw_status_new)
        update_status (wait_proc);
       if (wait_proc
@@ -4701,22 +4782,22 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
              if (nread == 0)
                break;
 
-              if (0 < nread)
-                {
+             if (0 < nread)
+               {
                  total_nread += nread;
                  got_some_input = 1;
                }
 #ifdef EIO
              else if (nread == -1 && EIO == errno)
-                break;
+               break;
 #endif
 #ifdef EAGAIN
              else if (nread == -1 && EAGAIN == errno)
-                break;
+               break;
 #endif
 #ifdef EWOULDBLOCK
              else if (nread == -1 && EWOULDBLOCK == errno)
-                break;
+               break;
 #endif
            }
          if (total_nread > 0 && do_display)
@@ -4810,12 +4891,14 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
              process_output_skip = 0;
            }
 #endif
-#ifdef HAVE_NS
-          nfds = ns_select
+#if defined (USE_GTK) || defined (HAVE_GCONF)
+          nfds = xg_select
+#elif defined (HAVE_NS)
+         nfds = ns_select
 #else
-          nfds = select
+         nfds = select
 #endif
-                        (max (max (max_process_desc, max_keyboard_desc),
+                       (max (max (max_process_desc, max_keyboard_desc),
                              max_gpm_desc) + 1,
                         &Available,
 #ifdef NON_BLOCKING_CONNECT
@@ -5038,11 +5121,16 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
                 It can't hurt.  */
              else if (nread == -1 && errno == EIO)
                {
-                 /* Clear the descriptor now, so we only raise the signal once.  */
-                 FD_CLR (channel, &input_wait_mask);
-                 FD_CLR (channel, &non_keyboard_wait_mask);
+                 /* Clear the descriptor now, so we only raise the
+                    signal once.  Don't do this if `process' is only
+                    a pty.  */
+                 if (XPROCESS (proc)->pid != -2)
+                   {
+                     FD_CLR (channel, &input_wait_mask);
+                     FD_CLR (channel, &non_keyboard_wait_mask);
 
-                 kill (getpid (), SIGCHLD);
+                     kill (getpid (), SIGCHLD);
+                   }
                }
 #endif /* HAVE_PTYS */
              /* If we can detect process termination, don't consider the process
@@ -5081,25 +5169,25 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 
 #ifdef GNU_LINUX
              /* getsockopt(,,SO_ERROR,,) is said to hang on some systems.
-                So only use it on systems where it is known to work.  */
+                So only use it on systems where it is known to work.  */
              {
-               int xlen = sizeof(xerrno);
-               if (getsockopt(channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen))
+               int xlen = sizeof (xerrno);
+               if (getsockopt (channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen))
                  xerrno = errno;
              }
 #else
              {
                struct sockaddr pname;
-               int pnamelen = sizeof(pname);
+               int pnamelen = sizeof (pname);
 
                /* If connection failed, getpeername will fail.  */
                xerrno = 0;
-               if (getpeername(channel, &pname, &pnamelen) < 0)
+               if (getpeername (channel, &pname, &pnamelen) < 0)
                  {
                    /* Obtain connect failure code through error slippage.  */
                    char dummy;
                    xerrno = errno;
-                   if (errno == ENOTCONN && read(channel, &dummy, 1) < 0)
+                   if (errno == ENOTCONN && read (channel, &dummy, 1) < 0)
                      xerrno = errno;
                  }
              }
@@ -5146,15 +5234,13 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 /* Given a list (FUNCTION ARGS...), apply FUNCTION to the ARGS.  */
 
 static Lisp_Object
-read_process_output_call (fun_and_args)
-     Lisp_Object fun_and_args;
+read_process_output_call (Lisp_Object fun_and_args)
 {
   return apply1 (XCAR (fun_and_args), XCDR (fun_and_args));
 }
 
 static Lisp_Object
-read_process_output_error_handler (error)
-     Lisp_Object error;
+read_process_output_error_handler (Lisp_Object error)
 {
   cmd_error_internal (error, "error in process filter: ");
   Vinhibit_quit = Qt;
@@ -5175,24 +5261,23 @@ read_process_output_error_handler (error)
    for decoding.  */
 
 static int
-read_process_output (proc, channel)
-     Lisp_Object proc;
-     register int channel;
+read_process_output (Lisp_Object proc, register int channel)
 {
   register int nbytes;
   char *chars;
   register Lisp_Object outstream;
-  register struct buffer *old = current_buffer;
   register struct Lisp_Process *p = XPROCESS (proc);
   register int opoint;
   struct coding_system *coding = proc_decode_coding_system[channel];
   int carryover = p->decoding_carryover;
   int readmax = 4096;
+  int count = SPECPDL_INDEX ();
+  Lisp_Object odeactivate;
 
   chars = (char *) alloca (carryover + readmax);
   if (carryover)
     /* See the comment above.  */
-    bcopy (SDATA (p->decoding_buf), chars, carryover);
+    memcpy (chars, SDATA (p->decoding_buf), carryover);
 
 #ifdef DATAGRAM_SOCKETS
   /* We have a working select, so proc_buffered_char is always -1.  */
@@ -5260,15 +5345,16 @@ read_process_output (proc, channel)
   /* Now set NBYTES how many bytes we must decode.  */
   nbytes += carryover;
 
+  odeactivate = Vdeactivate_mark;
+  /* 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 ());
+
   /* Read and dispose of the process output.  */
   outstream = p->filter;
   if (!NILP (outstream))
     {
-      /* We inhibit quit here instead of just catching it so that
-        hitting ^G when a filter happens to be running won't screw
-        it up.  */
-      int count = SPECPDL_INDEX ();
-      Lisp_Object odeactivate;
       Lisp_Object obuffer, okeymap;
       Lisp_Object text;
       int outer_running_asynch_code = running_asynch_code;
@@ -5276,10 +5362,12 @@ read_process_output (proc, channel)
 
       /* No need to gcpro these, because all we do with them later
         is test them for EQness, and none of them should be a string.  */
-      odeactivate = Vdeactivate_mark;
       XSETBUFFER (obuffer, current_buffer);
       okeymap = current_buffer->keymap;
 
+      /* We inhibit quit here instead of just catching it so that
+        hitting ^G when a filter happens to be running won't screw
+        it up.  */
       specbind (Qinhibit_quit, Qt);
       specbind (Qlast_nonmenu_event, Qt);
 
@@ -5333,8 +5421,8 @@ read_process_output (proc, channel)
        {
          if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
            p->decoding_buf = make_uninit_string (coding->carryover_bytes);
-         bcopy (coding->carryover, SDATA (p->decoding_buf),
-                coding->carryover_bytes);
+         memcpy (SDATA (p->decoding_buf), coding->carryover,
+                 coding->carryover_bytes);
          p->decoding_carryover = coding->carryover_bytes;
        }
       if (SBYTES (text) > 0)
@@ -5348,9 +5436,6 @@ read_process_output (proc, channel)
       restore_search_regs ();
       running_asynch_code = outer_running_asynch_code;
 
-      /* Handling the process output should not deactivate the mark.  */
-      Vdeactivate_mark = odeactivate;
-
       /* Restore waiting_for_user_input_p as it was
         when we were called, in case the filter clobbered it.  */
       waiting_for_user_input_p = waiting;
@@ -5366,25 +5451,19 @@ read_process_output (proc, channel)
           cause trouble (for example it would make sit_for return).  */
        if (waiting_for_user_input_p == -1)
          record_asynch_buffer_change ();
-
-      unbind_to (count, Qnil);
-      return nbytes;
     }
 
   /* If no filter, write into buffer if it isn't dead.  */
-  if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
+  else if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
     {
       Lisp_Object old_read_only;
       int old_begv, old_zv;
       int old_begv_byte, old_zv_byte;
-      Lisp_Object odeactivate;
       int before, before_byte;
       int opoint_byte;
       Lisp_Object text;
       struct buffer *b;
 
-      odeactivate = Vdeactivate_mark;
-
       Fset_buffer (p->buffer);
       opoint = PT;
       opoint_byte = PT_BYTE;
@@ -5434,8 +5513,8 @@ read_process_output (proc, channel)
        {
          if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
            p->decoding_buf = make_uninit_string (coding->carryover_bytes);
-         bcopy (coding->carryover, SDATA (p->decoding_buf),
-                coding->carryover_bytes);
+         memcpy (SDATA (p->decoding_buf), coding->carryover,
+                 coding->carryover_bytes);
          p->decoding_carryover = coding->carryover_bytes;
        }
       /* Adjust the multibyteness of TEXT to that of the buffer.  */
@@ -5482,13 +5561,14 @@ read_process_output (proc, channel)
       if (old_begv != BEGV || old_zv != ZV)
        Fnarrow_to_region (make_number (old_begv), make_number (old_zv));
 
-      /* Handling the process output should not deactivate the mark.  */
-      Vdeactivate_mark = odeactivate;
 
       current_buffer->read_only = old_read_only;
       SET_PT_BOTH (opoint, opoint_byte);
-      set_buffer_internal (old);
     }
+  /* Handling the process output should not deactivate the mark.  */
+  Vdeactivate_mark = odeactivate;
+
+  unbind_to (count, Qnil);
   return nbytes;
 }
 
@@ -5507,7 +5587,7 @@ jmp_buf send_process_frame;
 Lisp_Object process_sent_to;
 
 SIGTYPE
-send_process_trap ()
+send_process_trap (int ignore)
 {
   SIGNAL_THREAD_CHECK (SIGPIPE);
   sigunblock (sigmask (SIGPIPE));
@@ -5525,18 +5605,15 @@ send_process_trap ()
    This function can evaluate Lisp code and can garbage collect.  */
 
 static void
-send_process (proc, buf, len, object)
-     volatile Lisp_Object proc;
-     unsigned char *volatile buf;
-     volatile int len;
-     volatile Lisp_Object object;
+send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
+             volatile int len, volatile Lisp_Object object)
 {
   /* Use volatile to protect variables from being clobbered by longjmp.  */
   struct Lisp_Process *p = XPROCESS (proc);
   int rv;
   struct coding_system *coding;
   struct gcpro gcpro1;
-  SIGTYPE (*volatile old_sigpipe) ();
+  SIGTYPE (*volatile old_sigpipe) (int);
 
   GCPRO1 (object);
 
@@ -5608,7 +5685,8 @@ send_process (proc, buf, len, object)
        }
       else if (STRINGP (object))
        {
-         encode_coding_string (coding, object, 1);
+         encode_coding_object (coding, object, 0, 0, SCHARS (object),
+                               SBYTES (object), Qt);
        }
       else
        {
@@ -5617,7 +5695,8 @@ send_process (proc, buf, len, object)
        }
 
       len = coding->produced;
-      buf = SDATA (coding->dst_object);
+      object = coding->dst_object;
+      buf = SDATA (object);
     }
 
   if (pty_max_bytes == 0)
@@ -5643,39 +5722,11 @@ send_process (proc, buf, len, object)
        {
          int this = len;
 
-         /* Decide how much data we can send in one batch.
-            Long lines need to be split into multiple batches.  */
-         if (p->pty_flag)
-           {
-             /* Starting this at zero is always correct when not the first
-                 iteration because the previous iteration ended by sending C-d.
-                It may not be correct for the first iteration
-                if a partial line was sent in a separate send_process call.
-                If that proves worth handling, we need to save linepos
-                in the process object.  */
-             int linepos = 0;
-             unsigned char *ptr = (unsigned char *) buf;
-             unsigned char *end = (unsigned char *) buf + len;
-
-             /* Scan through this text for a line that is too long.  */
-             while (ptr != end && linepos < pty_max_bytes)
-               {
-                 if (*ptr == '\n')
-                   linepos = 0;
-                 else
-                   linepos++;
-                 ptr++;
-               }
-             /* If we found one, break the line there
-                and put in a C-d to force the buffer through.  */
-             this = ptr - buf;
-           }
-
          /* Send this batch, using one or more write calls.  */
          while (this > 0)
            {
              int outfd = p->outfd;
-             old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
+             old_sigpipe = (SIGTYPE (*) (int)) signal (SIGPIPE, send_process_trap);
 #ifdef DATAGRAM_SOCKETS
              if (DATAGRAM_CHAN_P (outfd))
                {
@@ -5774,11 +5825,6 @@ send_process (proc, buf, len, object)
              len -= rv;
              this -= rv;
            }
-
-         /* If we sent just part of the string, put in an EOF (C-d)
-            to force it through, before we send the rest.  */
-         if (len > 0)
-           Fprocess_send_eof (proc);
        }
     }
   else
@@ -5847,8 +5893,7 @@ Output from processes can arrive in between bunches.  */)
 /* Return the foreground process group for the tty/pty that
    the process P uses.  */
 static int
-emacs_get_tty_pgrp (p)
-     struct Lisp_Process *p;
+emacs_get_tty_pgrp (struct Lisp_Process *p)
 {
   int gid = -1;
 
@@ -5917,11 +5962,8 @@ return t unconditionally.  */)
    their uid, for which killpg would return an EPERM error.  */
 
 static void
-process_send_signal (process, signo, current_group, nomsg)
-     Lisp_Object process;
-     int signo;
-     Lisp_Object current_group;
-     int nomsg;
+process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
+                    int nomsg)
 {
   Lisp_Object proc;
   register struct Lisp_Process *p;
@@ -5952,7 +5994,7 @@ process_send_signal (process, signo, current_group, nomsg)
         by sending an input character to it.  */
 
       /* TERMIOS is the latest and bestest, and seems most likely to
-         work.  If the system has it, use it.  */
+        work.  If the system has it, use it.  */
 #ifdef HAVE_TERMIOS
       struct termios t;
       cc_t *sig_char = NULL;
@@ -6090,7 +6132,10 @@ process_send_signal (process, signo, current_group, nomsg)
       p->status = Qrun;
       p->tick = ++process_tick;
       if (!nomsg)
-       status_notify (NULL);
+       {
+         status_notify (NULL);
+         redisplay_preserve_echo_area (13);
+       }
       break;
 #endif /* ! defined (SIGCONT) */
     case SIGINT:
@@ -6298,7 +6343,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
       CHECK_SYMBOL (sigcode);
       name = SDATA (SYMBOL_NAME (sigcode));
 
-      if (!strncmp(name, "SIG", 3) || !strncmp(name, "sig", 3))
+      if (!strncmp (name, "SIG", 3) || !strncmp (name, "sig", 3))
        name += 3;
 
       if (0)
@@ -6472,11 +6517,11 @@ process has been transmitted to the serial port.  */)
       if (!proc_encode_coding_system[new_outfd])
        proc_encode_coding_system[new_outfd]
          = (struct coding_system *) xmalloc (sizeof (struct coding_system));
-      bcopy (proc_encode_coding_system[old_outfd],
-            proc_encode_coding_system[new_outfd],
-            sizeof (struct coding_system));
-      bzero (proc_encode_coding_system[old_outfd],
-            sizeof (struct coding_system));
+      memcpy (proc_encode_coding_system[new_outfd],
+             proc_encode_coding_system[old_outfd],
+             sizeof (struct coding_system));
+      memset (proc_encode_coding_system[old_outfd], 0,
+             sizeof (struct coding_system));
 
       XPROCESS (proc)->outfd = new_outfd;
     }
@@ -6487,8 +6532,7 @@ process has been transmitted to the serial port.  */)
    If `buffer' is nil, kill all processes  */
 
 void
-kill_buffer_processes (buffer)
-     Lisp_Object buffer;
+kill_buffer_processes (Lisp_Object buffer)
 {
   Lisp_Object tail, proc;
 
@@ -6533,8 +6577,7 @@ kill_buffer_processes (buffer)
 
 #ifdef SIGCHLD
 SIGTYPE
-sigchld_handler (signo)
-     int signo;
+sigchld_handler (int signo)
 {
   int old_errno = errno;
   Lisp_Object proc;
@@ -6555,7 +6598,7 @@ sigchld_handler (signo)
 #endif /* no WUNTRACED */
       /* Keep trying to get a status until we get a definitive result.  */
       do
-        {
+       {
          errno = 0;
          pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
        }
@@ -6566,11 +6609,6 @@ sigchld_handler (signo)
          /* PID == 0 means no processes found, PID == -1 means a real
             failure.  We have done all our job, so return.  */
 
-         /* USG systems forget handlers when they are used;
-            must reestablish each time */
-#if defined (USG) && !defined (POSIX_SIGNALS)
-         signal (signo, sigchld_handler);   /* WARNING - must come after wait3() */
-#endif
          errno = old_errno;
          return;
        }
@@ -6652,7 +6690,7 @@ sigchld_handler (signo)
          if (WIFEXITED (w))
            synch_process_retcode = WRETCODE (w);
          else if (WIFSIGNALED (w))
-            synch_process_termsig = WTERMSIG (w);
+           synch_process_termsig = WTERMSIG (w);
 
          /* Tell wait_reading_process_output that it needs to wake up and
             look around.  */
@@ -6670,10 +6708,7 @@ sigchld_handler (signo)
         to use up all the processes that have something to tell us.  */
 #if (defined WINDOWSNT \
      || (defined USG && !defined GNU_LINUX \
-         && !(defined HPUX && defined WNOHANG)))
-#if defined (USG) && ! defined (POSIX_SIGNALS)
-      signal (signo, sigchld_handler);
-#endif
+        && !(defined HPUX && defined WNOHANG)))
       errno = old_errno;
       return;
 #endif /* USG, but not HPUX with WNOHANG */
@@ -6683,16 +6718,14 @@ sigchld_handler (signo)
 \f
 
 static Lisp_Object
-exec_sentinel_unwind (data)
-     Lisp_Object data;
+exec_sentinel_unwind (Lisp_Object data)
 {
   XPROCESS (XCAR (data))->sentinel = XCDR (data);
   return Qnil;
 }
 
 static Lisp_Object
-exec_sentinel_error_handler (error)
-     Lisp_Object error;
+exec_sentinel_error_handler (Lisp_Object error)
 {
   cmd_error_internal (error, "error in process sentinel: ");
   Vinhibit_quit = Qt;
@@ -6702,8 +6735,7 @@ exec_sentinel_error_handler (error)
 }
 
 static void
-exec_sentinel (proc, reason)
-     Lisp_Object proc, reason;
+exec_sentinel (Lisp_Object proc, Lisp_Object reason)
 {
   Lisp_Object sentinel, obuffer, odeactivate, okeymap;
   register struct Lisp_Process *p = XPROCESS (proc);
@@ -6720,6 +6752,11 @@ exec_sentinel (proc, reason)
   XSETBUFFER (obuffer, current_buffer);
   okeymap = current_buffer->keymap;
 
+  /* 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 ());
+
   sentinel = p->sentinel;
   if (NILP (sentinel))
     return;
@@ -6730,7 +6767,7 @@ exec_sentinel (proc, reason)
   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);
-  specbind (Qlast_nonmenu_event, Qt);
+  specbind (Qlast_nonmenu_event, Qt); /* Why? --Stef  */
 
   /* In case we get recursively called,
      and we already saved the match data nonrecursively,
@@ -6783,8 +6820,7 @@ exec_sentinel (proc, reason)
    but can be done at other times.  */
 
 static void
-status_notify (deleting_process)
-     struct Lisp_Process *deleting_process;
+status_notify (struct Lisp_Process *deleting_process)
 {
   register Lisp_Object proc, buffer;
   Lisp_Object tail, msg;
@@ -6857,13 +6893,11 @@ status_notify (deleting_process)
             when a process becomes runnable.  */
          else if (!EQ (symbol, Qrun) && !NILP (buffer))
            {
-             Lisp_Object ro, tem;
+             Lisp_Object tem;
              struct buffer *old = current_buffer;
              int opoint, opoint_byte;
              int before, before_byte;
 
-             ro = XBUFFER (buffer)->read_only;
-
              /* Avoid error if buffer is deleted
                 (probably that's why the process is dead, too) */
              if (NILP (XBUFFER (buffer)->name))
@@ -6904,8 +6938,6 @@ status_notify (deleting_process)
     } /* end for */
 
   update_mode_lines++;  /* in case buffers use %s in mode-line-format */
-  redisplay_preserve_echo_area (13);
-
   UNGCPRO;
 }
 
@@ -6985,11 +7017,34 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
 
 
 \f
+/* Stop reading input from keyboard sources.  */
+
+void
+hold_keyboard_input (void)
+{
+  kbd_is_on_hold = 1;
+}
+
+/* Resume reading input from keyboard sources.  */
+
+void
+unhold_keyboard_input (void)
+{
+  kbd_is_on_hold = 0;
+}
+
+/* Return non-zero if keyboard input is on hold, zero otherwise.  */
+
+int
+kbd_on_hold_p (void)
+{
+  return kbd_is_on_hold;
+}
+
 /* Add DESC to the set of keyboard input descriptors.  */
 
 void
-add_keyboard_wait_descriptor (desc)
-     int desc;
+add_keyboard_wait_descriptor (int desc)
 {
   FD_SET (desc, &input_wait_mask);
   FD_SET (desc, &non_process_wait_mask);
@@ -7000,8 +7055,7 @@ add_keyboard_wait_descriptor (desc)
 static int add_gpm_wait_descriptor_called_flag;
 
 void
-add_gpm_wait_descriptor (desc)
-     int desc;
+add_gpm_wait_descriptor (int desc)
 {
   if (! add_gpm_wait_descriptor_called_flag)
     FD_CLR (0, &input_wait_mask);
@@ -7015,8 +7069,7 @@ add_gpm_wait_descriptor (desc)
 /* From now on, do not expect DESC to give keyboard input.  */
 
 void
-delete_keyboard_wait_descriptor (desc)
-     int desc;
+delete_keyboard_wait_descriptor (int desc)
 {
   int fd;
   int lim = max_keyboard_desc;
@@ -7033,8 +7086,7 @@ delete_keyboard_wait_descriptor (desc)
 }
 
 void
-delete_gpm_wait_descriptor (desc)
-     int desc;
+delete_gpm_wait_descriptor (int desc)
 {
   int fd;
   int lim = max_gpm_desc;
@@ -7054,8 +7106,7 @@ delete_gpm_wait_descriptor (desc)
    that corresponds to one of the keyboard input descriptors.  */
 
 static int
-keyboard_bit_set (mask)
-     SELECT_TYPE *mask;
+keyboard_bit_set (fd_set *mask)
 {
   int fd;
 
@@ -7069,430 +7120,31 @@ keyboard_bit_set (mask)
 \f
 /* Enumeration of and access to system processes a-la ps(1).  */
 
-#if HAVE_PROCFS
-
-/* Process enumeration and access via /proc.  */
-
-static Lisp_Object
-procfs_list_system_processes ()
-{
-  Lisp_Object procdir, match, proclist, next;
-  struct gcpro gcpro1, gcpro2;
-  register Lisp_Object tail;
-
-  GCPRO2 (procdir, match);
-  /* For every process on the system, there's a directory in the
-     "/proc" pseudo-directory whose name is the numeric ID of that
-     process.  */
-  procdir = build_string ("/proc");
-  match = build_string ("[0-9]+");
-  proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
-
-  /* `proclist' gives process IDs as strings.  Destructively convert
-     each string into a number.  */
-  for (tail = proclist; CONSP (tail); tail = next)
-    {
-      next = XCDR (tail);
-      XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
-    }
-  UNGCPRO;
-
-  /* directory_files_internal returns the files in reverse order; undo
-     that.  */
-  proclist = Fnreverse (proclist);
-  return proclist;
-}
-
-static void
-time_from_jiffies (unsigned long long tval, long hz,
-                  time_t *sec, unsigned *usec)
-{
-  unsigned long long ullsec;
-
-  *sec = tval / hz;
-  ullsec = *sec;
-  tval -= ullsec * hz;
-  /* Careful: if HZ > 1 million, then integer division by it yields zero.  */
-  if (hz <= 1000000)
-    *usec = tval * 1000000 / hz;
-  else
-    *usec = tval / (hz / 1000000);
-}
-
-static Lisp_Object
-ltime_from_jiffies (unsigned long long tval, long hz)
-{
-  time_t sec;
-  unsigned usec;
-
-  time_from_jiffies (tval, hz, &sec, &usec);
-
-  return list3 (make_number ((sec >> 16) & 0xffff),
-               make_number (sec & 0xffff),
-               make_number (usec));
-}
-
-static void
-get_up_time (time_t *sec, unsigned *usec)
-{
-  FILE *fup;
-  
-  *sec = *usec = 0;
-
-  BLOCK_INPUT;
-  fup = fopen ("/proc/uptime", "r");
-
-  if (fup)
-    {
-      double uptime, idletime;
-
-      /* The numbers in /proc/uptime use C-locale decimal point, but
-        we already set ourselves to the C locale (see `fixup_locale'
-        in emacs.c).  */
-      if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
-       {
-         *sec = uptime;
-         *usec = (uptime - *sec) * 1000000;
-       }
-      fclose (fup);
-    }
-  UNBLOCK_INPUT;
-}
-
-#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
-#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
-
-static Lisp_Object
-procfs_ttyname (rdev)
-{
-  FILE *fdev = NULL;
-  char name[PATH_MAX];
-
-  BLOCK_INPUT;
-  fdev = fopen ("/proc/tty/drivers", "r");
-
-  if (fdev)
-    {
-      unsigned major;
-      unsigned long minor_beg, minor_end;
-      char minor[25];  /* 2 32-bit numbers + dash */
-      char *endp;
-
-      while (!feof (fdev) && !ferror (fdev))
-       {
-         if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
-             && major == MAJOR (rdev))
-           {
-             minor_beg = strtoul (minor, &endp, 0);
-             if (*endp == '\0')
-               minor_end = minor_beg;
-             else if (*endp == '-')
-               minor_end = strtoul (endp + 1, &endp, 0);
-             else
-               continue;
-
-             if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
-               {
-                 sprintf (name + strlen (name), "%lu", MINOR (rdev));
-                 break;
-               }
-           }
-       }
-      fclose (fdev);
-    }
-  UNBLOCK_INPUT;
-  return build_string (name);
-}
-
-static unsigned long
-procfs_get_total_memory (void)
-{
-  FILE *fmem = NULL;
-  unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
-
-  BLOCK_INPUT;
-  fmem = fopen ("/proc/meminfo", "r");
-
-  if (fmem)
-    {
-      unsigned long entry_value;
-      char entry_name[20];     /* the longest I saw is 13+1 */
-
-      while (!feof (fmem) && !ferror (fmem))
-       {
-         if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
-             && strcmp (entry_name, "MemTotal:") == 0)
-           {
-             retval = entry_value;
-             break;
-           }
-       }
-      fclose (fmem);
-    }
-  UNBLOCK_INPUT;
-  return retval;
-}
-
-static Lisp_Object
-procfs_system_process_attributes (pid)
-     Lisp_Object pid;
-{
-  char procfn[PATH_MAX], fn[PATH_MAX];
-  struct stat st;
-  struct passwd *pw;
-  struct group *gr;
-  long clocks_per_sec;
-  char *procfn_end;
-  char procbuf[1025], *p, *q;
-  int fd;
-  ssize_t nread;
-  char cmd[PATH_MAX];
-  char *cmdline = NULL;
-  size_t cmdsize;
-  int c;
-  int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
-  unsigned long long utime, stime, cutime, cstime, start;
-  long priority, nice, rss;
-  unsigned long minflt, majflt, cminflt, cmajflt, vsize;
-  time_t sec;
-  unsigned usec;
-  EMACS_TIME tnow, tstart, tboot, telapsed,ttotal;
-  double pcpu, pmem;
-  Lisp_Object attrs = Qnil;
-  Lisp_Object cmd_str, decoded_cmd, tem;
-  struct gcpro gcpro1, gcpro2;
-  EMACS_INT uid_eint, gid_eint;
-
-  CHECK_NUMBER_OR_FLOAT (pid);
-  proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
-  sprintf (procfn, "/proc/%lu", proc_id);
-  if (stat (procfn, &st) < 0)
-    return attrs;
-
-  GCPRO2 (attrs, decoded_cmd);
-
-  /* euid egid */
-  uid = st.st_uid;
-  /* Use of EMACS_INT stops GCC whining about limited range of data type.  */
-  uid_eint = uid;
-  attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
-  BLOCK_INPUT;
-  pw = (struct passwd *) getpwuid (uid);
-  UNBLOCK_INPUT;
-  if (pw)
-    attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
-
-  gid = st.st_gid;
-  gid_eint = gid;
-  attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
-  BLOCK_INPUT;
-  gr = (struct group *) getgrgid (gid);
-  UNBLOCK_INPUT;
-  if (gr)
-    attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
-
-  strcpy (fn, procfn);
-  procfn_end = fn + strlen (fn);
-  strcpy (procfn_end, "/stat");
-  fd = emacs_open (fn, O_RDONLY, 0);
-  if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof(procbuf) - 1)) > 0)
-    {
-      procbuf[nread] = '\0';
-      p = procbuf;
-
-      p = strchr (p, '(') + 1;
-      q = strchr (p, ')');
-      /* comm */
-      if (q > p)
-       {
-         memcpy (cmd, p, q - p);
-         cmd[q - p] = '\0';
-       }
-      else
-       strcpy (cmd, "???");
-      /* Command name is encoded in locale-coding-system; decode it.  */
-      cmd_str = make_unibyte_string (cmd, q ? q - p : 3);
-      decoded_cmd = code_convert_string_norecord (cmd_str,
-                                                 Vlocale_coding_system, 0);
-      attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
-
-      if (q)
-       {
-         EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
-         p = q + 2;
-         /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
-         sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
-                 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
-                 &minflt, &cminflt, &majflt, &cmajflt,
-                 &utime, &stime, &cutime, &cstime,
-                 &priority, &nice, &thcount, &start, &vsize, &rss);
-         {
-           char state_str[2];
-
-           state_str[0] = c;
-           state_str[1] = '\0';
-           tem =  build_string (state_str);
-           attrs = Fcons (Fcons (Qstate, tem), attrs);
-         }
-         /* Stops GCC whining about limited range of data type.  */
-         ppid_eint = ppid;
-         pgrp_eint = pgrp;
-         sess_eint = sess;
-         tpgid_eint = tpgid;
-         thcount_eint = thcount;
-         attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
-         attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
-         attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
-         attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
-         attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
-         attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
-         attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
-         attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
-         attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
-         clocks_per_sec = sysconf (_SC_CLK_TCK);
-         if (clocks_per_sec < 0)
-           clocks_per_sec = 100;
-         attrs = Fcons (Fcons (Qutime,
-                               ltime_from_jiffies (utime, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qstime,
-                               ltime_from_jiffies (stime, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qcutime,
-                               ltime_from_jiffies (cutime, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qcstime,
-                               ltime_from_jiffies (cstime, clocks_per_sec)),
-                        attrs);
-         attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
-         attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
-         attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
-         EMACS_GET_TIME (tnow);
-         get_up_time (&sec, &usec);
-         EMACS_SET_SECS (telapsed, sec);
-         EMACS_SET_USECS (telapsed, usec);
-         EMACS_SUB_TIME (tboot, tnow, telapsed);
-         time_from_jiffies (start, clocks_per_sec, &sec, &usec);
-         EMACS_SET_SECS (tstart, sec);
-         EMACS_SET_USECS (tstart, usec);
-         EMACS_ADD_TIME (tstart, tboot, tstart);
-         attrs = Fcons (Fcons (Qstart,
-                               list3 (make_number
-                                      ((EMACS_SECS (tstart) >> 16) & 0xffff),
-                                      make_number
-                                      (EMACS_SECS (tstart) & 0xffff),
-                                      make_number
-                                      (EMACS_USECS (tstart)))),
-                        attrs);
-         attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
-         attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
-         EMACS_SUB_TIME (telapsed, tnow, tstart);
-         attrs = Fcons (Fcons (Qetime,
-                               list3 (make_number
-                                      ((EMACS_SECS (telapsed) >> 16) & 0xffff),
-                                      make_number
-                                      (EMACS_SECS (telapsed) & 0xffff),
-                                      make_number
-                                      (EMACS_USECS (telapsed)))),
-                        attrs);
-         time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec);
-         pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
-         attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
-         pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
-         if (pmem > 100)
-           pmem = 100;
-         attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
-       }
-    }
-  if (fd >= 0)
-    emacs_close (fd);
-
-  /* args */
-  strcpy (procfn_end, "/cmdline");
-  fd = emacs_open (fn, O_RDONLY, 0);
-  if (fd >= 0)
-    {
-      for (cmdsize = 0; emacs_read (fd, (char *)&c, 1) == 1; cmdsize++)
-       {
-         if (isspace (c) || c == '\\')
-           cmdsize++;  /* for later quoting, see below */
-       }
-      if (cmdsize)
-       {
-         cmdline = xmalloc (cmdsize + 1);
-         lseek (fd, 0L, SEEK_SET);
-         cmdline[0] = '\0';
-         if ((nread = read (fd, cmdline, cmdsize)) >= 0)
-           cmdline[nread++] = '\0';
-         /* We don't want trailing null characters.  */
-         for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
-           nread--;
-         for (p = cmdline; p < cmdline + nread; p++)
-           {
-             /* Escape-quote whitespace and backslashes.  */
-             if (isspace (*p) || *p == '\\')
-               {
-                 memmove (p + 1, p, nread - (p - cmdline));
-                 nread++;
-                 *p++ = '\\';
-               }
-             else if (*p == '\0')
-               *p = ' ';
-           }
-         cmdsize = nread;
-       }
-      else
-       {
-         cmdsize = strlen (cmd) + 2;
-         cmdline = xmalloc (cmdsize + 1);
-         strcpy (cmdline, "[");
-         strcat (strcat (cmdline, cmd), "]");
-       }
-      emacs_close (fd);
-      /* Command line is encoded in locale-coding-system; decode it.  */
-      cmd_str = make_unibyte_string (cmdline, cmdsize);
-      decoded_cmd = code_convert_string_norecord (cmd_str,
-                                                 Vlocale_coding_system, 0);
-      xfree (cmdline);
-      attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
-    }
-
-  UNGCPRO;
-  return attrs;
-}
-
-#endif /* !HAVE_PROCFS */
-
 DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes,
        0, 0, 0,
        doc: /* Return a list of numerical process IDs of all running processes.
 If this functionality is unsupported, return nil.
 
-See `system-process-attributes' for getting attributes of a process
-given its ID.  */)
+See `process-attributes' for getting attributes of a process given its ID.  */)
     ()
 {
-#ifdef LISTPROC
-  return LISTPROC ();
-#else
-  return Qnil;
-#endif
+  return list_system_processes ();
 }
 
-DEFUN ("system-process-attributes", Fsystem_process_attributes,
-       Ssystem_process_attributeses, 1, 1, 0,
+DEFUN ("process-attributes", Fprocess_attributes,
+       Sprocess_attributes, 1, 1, 0,
        doc: /* Return attributes of the process given by its PID, a number.
 
 Value is an alist where each element is a cons cell of the form
 
-    \(ATTR . VALUE)
+    \(KEY . VALUE)
 
 If this functionality is unsupported, the value is nil.
 
 See `list-system-processes' for getting a list of all process IDs.
 
-The attributes that this function may return are listed below,
-together with the type of the associated value (in parentheses).
+The KEYs of the attributes that this function may return are listed
+below, together with the type of the associated VALUE (in parentheses).
 Not all platforms support all of these attributes; unsupported
 attributes will not appear in the returned alist.
 Unless explicitly indicated otherwise, numbers can have either
@@ -7515,8 +7167,10 @@ integer or floating point values.
  cmajflt -- cumulative number of major page faults (number)
  utime   -- user time used by the process, in the (HIGH LOW USEC) format
  stime   -- system time used by the process, in the (HIGH LOW USEC) format
+ time    -- sum of utime and stime, in the (HIGH LOW USEC) format
  cutime  -- user time used by the process and its children, (HIGH LOW USEC)
  cstime  -- system time used by the process and its children, (HIGH LOW USEC)
+ ctime   -- sum of cutime and cstime, in the (HIGH LOW USEC) format
  pri     -- priority of the process (number)
  nice    -- nice value of the process (number)
  thcount -- process thread count (number)
@@ -7532,15 +7186,11 @@ integer or floating point values.
 
     Lisp_Object pid;
 {
-#ifdef PROCATTR
-  return PROCATTR (pid);
-#else
-  return Qnil;
-#endif
+  return system_process_attributes (pid);
 }
 \f
 void
-init_process ()
+init_process (void)
 {
   register int i;
 
@@ -7584,19 +7234,19 @@ init_process ()
       chan_process[i] = Qnil;
       proc_buffered_char[i] = -1;
     }
-  bzero (proc_decode_coding_system, sizeof proc_decode_coding_system);
-  bzero (proc_encode_coding_system, sizeof proc_encode_coding_system);
+  memset (proc_decode_coding_system, 0, sizeof proc_decode_coding_system);
+  memset (proc_encode_coding_system, 0, sizeof proc_encode_coding_system);
 #ifdef DATAGRAM_SOCKETS
-  bzero (datagram_address, sizeof datagram_address);
+  memset (datagram_address, 0, sizeof datagram_address);
 #endif
 
 #ifdef HAVE_SOCKETS
  {
    Lisp_Object subfeatures = Qnil;
-   struct socket_options *sopt;
+   const struct socket_options *sopt;
 
 #define ADD_SUBFEATURE(key, val) \
-  subfeatures = Fcons (Fcons (key, Fcons (val, Qnil)), subfeatures)
+  subfeatures = pure_cons (pure_cons (key, pure_cons (val, Qnil)), subfeatures)
 
 #ifdef NON_BLOCKING_CONNECT
    ADD_SUBFEATURE (QCnowait, Qt);
@@ -7604,6 +7254,9 @@ init_process ()
 #ifdef DATAGRAM_SOCKETS
    ADD_SUBFEATURE (QCtype, Qdatagram);
 #endif
+#ifdef HAVE_SEQPACKET
+   ADD_SUBFEATURE (QCtype, Qseqpacket);
+#endif
 #ifdef HAVE_LOCAL_SOCKETS
    ADD_SUBFEATURE (QCfamily, Qlocal);
 #endif
@@ -7619,9 +7272,9 @@ init_process ()
 #endif
 
    for (sopt = socket_options; sopt->name; sopt++)
-     subfeatures = Fcons (intern (sopt->name), subfeatures);
+     subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures);
 
-   Fprovide (intern ("make-network-process"), subfeatures);
+   Fprovide (intern_c_string ("make-network-process"), subfeatures);
  }
 #endif /* HAVE_SOCKETS */
 
@@ -7630,7 +7283,7 @@ init_process ()
      processes.  As such, we only change the default value.  */
  if (initialized)
   {
-    char *release = get_operating_system_release();
+    char *release = get_operating_system_release ();
     if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
                                    && release[1] == '.')) {
       Vprocess_connection_type = Qnil;
@@ -7640,111 +7293,113 @@ init_process ()
 }
 
 void
-syms_of_process ()
+syms_of_process (void)
 {
-  Qprocessp = intern ("processp");
+  Qprocessp = intern_c_string ("processp");
   staticpro (&Qprocessp);
-  Qrun = intern ("run");
+  Qrun = intern_c_string ("run");
   staticpro (&Qrun);
-  Qstop = intern ("stop");
+  Qstop = intern_c_string ("stop");
   staticpro (&Qstop);
-  Qsignal = intern ("signal");
+  Qsignal = intern_c_string ("signal");
   staticpro (&Qsignal);
 
   /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
      here again.
 
-     Qexit = intern ("exit");
+     Qexit = intern_c_string ("exit");
      staticpro (&Qexit); */
 
-  Qopen = intern ("open");
+  Qopen = intern_c_string ("open");
   staticpro (&Qopen);
-  Qclosed = intern ("closed");
+  Qclosed = intern_c_string ("closed");
   staticpro (&Qclosed);
-  Qconnect = intern ("connect");
+  Qconnect = intern_c_string ("connect");
   staticpro (&Qconnect);
-  Qfailed = intern ("failed");
+  Qfailed = intern_c_string ("failed");
   staticpro (&Qfailed);
-  Qlisten = intern ("listen");
+  Qlisten = intern_c_string ("listen");
   staticpro (&Qlisten);
-  Qlocal = intern ("local");
+  Qlocal = intern_c_string ("local");
   staticpro (&Qlocal);
-  Qipv4 = intern ("ipv4");
+  Qipv4 = intern_c_string ("ipv4");
   staticpro (&Qipv4);
 #ifdef AF_INET6
-  Qipv6 = intern ("ipv6");
+  Qipv6 = intern_c_string ("ipv6");
   staticpro (&Qipv6);
 #endif
-  Qdatagram = intern ("datagram");
+  Qdatagram = intern_c_string ("datagram");
   staticpro (&Qdatagram);
+  Qseqpacket = intern_c_string ("seqpacket");
+  staticpro (&Qseqpacket);
 
-  QCport = intern (":port");
+  QCport = intern_c_string (":port");
   staticpro (&QCport);
-  QCspeed = intern (":speed");
+  QCspeed = intern_c_string (":speed");
   staticpro (&QCspeed);
-  QCprocess = intern (":process");
+  QCprocess = intern_c_string (":process");
   staticpro (&QCprocess);
 
-  QCbytesize = intern (":bytesize");
+  QCbytesize = intern_c_string (":bytesize");
   staticpro (&QCbytesize);
-  QCstopbits = intern (":stopbits");
+  QCstopbits = intern_c_string (":stopbits");
   staticpro (&QCstopbits);
-  QCparity = intern (":parity");
+  QCparity = intern_c_string (":parity");
   staticpro (&QCparity);
-  Qodd = intern ("odd");
+  Qodd = intern_c_string ("odd");
   staticpro (&Qodd);
-  Qeven = intern ("even");
+  Qeven = intern_c_string ("even");
   staticpro (&Qeven);
-  QCflowcontrol = intern (":flowcontrol");
+  QCflowcontrol = intern_c_string (":flowcontrol");
   staticpro (&QCflowcontrol);
-  Qhw = intern ("hw");
+  Qhw = intern_c_string ("hw");
   staticpro (&Qhw);
-  Qsw = intern ("sw");
+  Qsw = intern_c_string ("sw");
   staticpro (&Qsw);
-  QCsummary = intern (":summary");
+  QCsummary = intern_c_string (":summary");
   staticpro (&QCsummary);
 
-  Qreal = intern ("real");
+  Qreal = intern_c_string ("real");
   staticpro (&Qreal);
-  Qnetwork = intern ("network");
+  Qnetwork = intern_c_string ("network");
   staticpro (&Qnetwork);
-  Qserial = intern ("serial");
+  Qserial = intern_c_string ("serial");
   staticpro (&Qserial);
 
-  QCname = intern (":name");
+  QCname = intern_c_string (":name");
   staticpro (&QCname);
-  QCbuffer = intern (":buffer");
+  QCbuffer = intern_c_string (":buffer");
   staticpro (&QCbuffer);
-  QChost = intern (":host");
+  QChost = intern_c_string (":host");
   staticpro (&QChost);
-  QCservice = intern (":service");
+  QCservice = intern_c_string (":service");
   staticpro (&QCservice);
-  QCtype = intern (":type");
+  QCtype = intern_c_string (":type");
   staticpro (&QCtype);
-  QClocal = intern (":local");
+  QClocal = intern_c_string (":local");
   staticpro (&QClocal);
-  QCremote = intern (":remote");
+  QCremote = intern_c_string (":remote");
   staticpro (&QCremote);
-  QCcoding = intern (":coding");
+  QCcoding = intern_c_string (":coding");
   staticpro (&QCcoding);
-  QCserver = intern (":server");
+  QCserver = intern_c_string (":server");
   staticpro (&QCserver);
-  QCnowait = intern (":nowait");
+  QCnowait = intern_c_string (":nowait");
   staticpro (&QCnowait);
-  QCsentinel = intern (":sentinel");
+  QCsentinel = intern_c_string (":sentinel");
   staticpro (&QCsentinel);
-  QClog = intern (":log");
+  QClog = intern_c_string (":log");
   staticpro (&QClog);
-  QCnoquery = intern (":noquery");
+  QCnoquery = intern_c_string (":noquery");
   staticpro (&QCnoquery);
-  QCstop = intern (":stop");
+  QCstop = intern_c_string (":stop");
   staticpro (&QCstop);
-  QCoptions = intern (":options");
+  QCoptions = intern_c_string (":options");
   staticpro (&QCoptions);
-  QCplist = intern (":plist");
+  QCplist = intern_c_string (":plist");
   staticpro (&QCplist);
 
-  Qlast_nonmenu_event = intern ("last-nonmenu-event");
+  Qlast_nonmenu_event = intern_c_string ("last-nonmenu-event");
   staticpro (&Qlast_nonmenu_event);
 
   staticpro (&Vprocess_alist);
@@ -7752,63 +7407,67 @@ syms_of_process ()
   staticpro (&deleted_pid_list);
 #endif
 
-  Qeuid = intern ("euid");
+  Qeuid = intern_c_string ("euid");
   staticpro (&Qeuid);
-  Qegid = intern ("egid");
+  Qegid = intern_c_string ("egid");
   staticpro (&Qegid);
-  Quser = intern ("user");
+  Quser = intern_c_string ("user");
   staticpro (&Quser);
-  Qgroup = intern ("group");
+  Qgroup = intern_c_string ("group");
   staticpro (&Qgroup);
-  Qcomm = intern ("comm");
+  Qcomm = intern_c_string ("comm");
   staticpro (&Qcomm);
-  Qstate = intern ("state");
+  Qstate = intern_c_string ("state");
   staticpro (&Qstate);
-  Qppid = intern ("ppid");
+  Qppid = intern_c_string ("ppid");
   staticpro (&Qppid);
-  Qpgrp = intern ("pgrp");
+  Qpgrp = intern_c_string ("pgrp");
   staticpro (&Qpgrp);
-  Qsess = intern ("sess");
+  Qsess = intern_c_string ("sess");
   staticpro (&Qsess);
-  Qttname = intern ("ttname");
+  Qttname = intern_c_string ("ttname");
   staticpro (&Qttname);
-  Qtpgid = intern ("tpgid");
+  Qtpgid = intern_c_string ("tpgid");
   staticpro (&Qtpgid);
-  Qminflt = intern ("minflt");
+  Qminflt = intern_c_string ("minflt");
   staticpro (&Qminflt);
-  Qmajflt = intern ("majflt");
+  Qmajflt = intern_c_string ("majflt");
   staticpro (&Qmajflt);
-  Qcminflt = intern ("cminflt");
+  Qcminflt = intern_c_string ("cminflt");
   staticpro (&Qcminflt);
-  Qcmajflt = intern ("cmajflt");
+  Qcmajflt = intern_c_string ("cmajflt");
   staticpro (&Qcmajflt);
-  Qutime = intern ("utime");
+  Qutime = intern_c_string ("utime");
   staticpro (&Qutime);
-  Qstime = intern ("stime");
+  Qstime = intern_c_string ("stime");
   staticpro (&Qstime);
-  Qcutime = intern ("cutime");
+  Qtime = intern_c_string ("time");
+  staticpro (&Qtime);
+  Qcutime = intern_c_string ("cutime");
   staticpro (&Qcutime);
-  Qcstime = intern ("cstime");
+  Qcstime = intern_c_string ("cstime");
   staticpro (&Qcstime);
-  Qpri = intern ("pri");
+  Qctime = intern_c_string ("ctime");
+  staticpro (&Qctime);
+  Qpri = intern_c_string ("pri");
   staticpro (&Qpri);
-  Qnice = intern ("nice");
+  Qnice = intern_c_string ("nice");
   staticpro (&Qnice);
-  Qthcount = intern ("thcount");
+  Qthcount = intern_c_string ("thcount");
   staticpro (&Qthcount);
-  Qstart = intern ("start");
+  Qstart = intern_c_string ("start");
   staticpro (&Qstart);
-  Qvsize = intern ("vsize");
+  Qvsize = intern_c_string ("vsize");
   staticpro (&Qvsize);
-  Qrss = intern ("rss");
+  Qrss = intern_c_string ("rss");
   staticpro (&Qrss);
-  Qetime = intern ("etime");
+  Qetime = intern_c_string ("etime");
   staticpro (&Qetime);
-  Qpcpu = intern ("pcpu");
+  Qpcpu = intern_c_string ("pcpu");
   staticpro (&Qpcpu);
-  Qpmem = intern ("pmem");
+  Qpmem = intern_c_string ("pmem");
   staticpro (&Qpmem);
-  Qargs = intern ("args");
+  Qargs = intern_c_string ("args");
   staticpro (&Qargs);
 
   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
@@ -7906,7 +7565,7 @@ The variable takes effect when `start-process' is called.  */);
   defsubr (&Sset_process_filter_multibyte);
   defsubr (&Sprocess_filter_multibyte_p);
   defsubr (&Slist_system_processes);
-  defsubr (&Ssystem_process_attributeses);
+  defsubr (&Sprocess_attributes);
 }
 
 \f
@@ -7917,6 +7576,7 @@ The variable takes effect when `start-process' is called.  */);
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <fcntl.h>
+#include <setjmp.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -7933,7 +7593,12 @@ extern int frame_garbaged;
 extern EMACS_TIME timer_check ();
 extern int timers_run;
 
-Lisp_Object QCtype;
+Lisp_Object QCtype, QCname;
+
+Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
+Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
+Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
+Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
 
 /* As described above, except assuming that there are no subprocesses:
 
@@ -8200,27 +7865,26 @@ DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes,
        doc: /* Return a list of numerical process IDs of all running processes.
 If this functionality is unsupported, return nil.
 
-See `system-process-attributes' for getting attributes of a process
-given its ID.  */)
+See `process-attributes' for getting attributes of a process given its ID.  */)
     ()
 {
-  return Qnil;
+  return list_system_processes ();
 }
 
-DEFUN ("system-process-attributes", Fsystem_process_attributes,
-       Ssystem_process_attributeses, 1, 1, 0,
+DEFUN ("process-attributes", Fprocess_attributes,
+       Sprocess_attributes, 1, 1, 0,
        doc: /* Return attributes of the process given by its PID, a number.
 
 Value is an alist where each element is a cons cell of the form
 
-    \(ATTR . VALUE)
+    \(KEY . VALUE)
 
 If this functionality is unsupported, the value is nil.
 
 See `list-system-processes' for getting a list of all process IDs.
 
-The attributes that this function may return are listed below,
-together with the type of the associated value (in parentheses).
+The KEYs of the attributes that this function may return are listed
+below, together with the type of the associated VALUE (in parentheses).
 Not all platforms support all of these attributes; unsupported
 attributes will not appear in the returned alist.
 Unless explicitly indicated otherwise, numbers can have either
@@ -8243,8 +7907,10 @@ integer or floating point values.
  cmajflt -- cumulative number of major page faults (number)
  utime   -- user time used by the process, in the (HIGH LOW USEC) format
  stime   -- system time used by the process, in the (HIGH LOW USEC) format
+ time    -- sum of utime and stime, in the (HIGH LOW USEC) format
  cutime  -- user time used by the process and its children, (HIGH LOW USEC)
  cstime  -- system time used by the process and its children, (HIGH LOW USEC)
+ ctime   -- sum of cutime and cstime, in the (HIGH LOW USEC) format
  pri     -- priority of the process (number)
  nice    -- nice value of the process (number)
  thcount -- process thread count (number)
@@ -8260,24 +7926,93 @@ integer or floating point values.
 
     Lisp_Object pid;
 {
-  return Qnil;
+  return system_process_attributes (pid);
 }
 
 void
 init_process ()
 {
+  kbd_is_on_hold = 0;
 }
 
 void
 syms_of_process ()
 {
-  QCtype = intern (":type");
+  QCtype = intern_c_string (":type");
   staticpro (&QCtype);
+  QCname = intern_c_string (":name");
+  staticpro (&QCname);
+  QCtype = intern_c_string (":type");
+  staticpro (&QCtype);
+  QCname = intern_c_string (":name");
+  staticpro (&QCname);
+  Qeuid = intern_c_string ("euid");
+  staticpro (&Qeuid);
+  Qegid = intern_c_string ("egid");
+  staticpro (&Qegid);
+  Quser = intern_c_string ("user");
+  staticpro (&Quser);
+  Qgroup = intern_c_string ("group");
+  staticpro (&Qgroup);
+  Qcomm = intern_c_string ("comm");
+  staticpro (&Qcomm);
+  Qstate = intern_c_string ("state");
+  staticpro (&Qstate);
+  Qppid = intern_c_string ("ppid");
+  staticpro (&Qppid);
+  Qpgrp = intern_c_string ("pgrp");
+  staticpro (&Qpgrp);
+  Qsess = intern_c_string ("sess");
+  staticpro (&Qsess);
+  Qttname = intern_c_string ("ttname");
+  staticpro (&Qttname);
+  Qtpgid = intern_c_string ("tpgid");
+  staticpro (&Qtpgid);
+  Qminflt = intern_c_string ("minflt");
+  staticpro (&Qminflt);
+  Qmajflt = intern_c_string ("majflt");
+  staticpro (&Qmajflt);
+  Qcminflt = intern_c_string ("cminflt");
+  staticpro (&Qcminflt);
+  Qcmajflt = intern_c_string ("cmajflt");
+  staticpro (&Qcmajflt);
+  Qutime = intern_c_string ("utime");
+  staticpro (&Qutime);
+  Qstime = intern_c_string ("stime");
+  staticpro (&Qstime);
+  Qtime = intern_c_string ("time");
+  staticpro (&Qtime);
+  Qcutime = intern_c_string ("cutime");
+  staticpro (&Qcutime);
+  Qcstime = intern_c_string ("cstime");
+  staticpro (&Qcstime);
+  Qctime = intern_c_string ("ctime");
+  staticpro (&Qctime);
+  Qpri = intern_c_string ("pri");
+  staticpro (&Qpri);
+  Qnice = intern_c_string ("nice");
+  staticpro (&Qnice);
+  Qthcount = intern_c_string ("thcount");
+  staticpro (&Qthcount);
+  Qstart = intern_c_string ("start");
+  staticpro (&Qstart);
+  Qvsize = intern_c_string ("vsize");
+  staticpro (&Qvsize);
+  Qrss = intern_c_string ("rss");
+  staticpro (&Qrss);
+  Qetime = intern_c_string ("etime");
+  staticpro (&Qetime);
+  Qpcpu = intern_c_string ("pcpu");
+  staticpro (&Qpcpu);
+  Qpmem = intern_c_string ("pmem");
+  staticpro (&Qpmem);
+  Qargs = intern_c_string ("args");
+  staticpro (&Qargs);
 
   defsubr (&Sget_buffer_process);
   defsubr (&Sprocess_inherit_coding_system_flag);
   defsubr (&Slist_system_processes);
-  defsubr (&Ssystem_process_attributeses);
+  defsubr (&Sprocess_attributes);
 }
 
 \f