]> code.delx.au - gnu-emacs/blobdiff - src/process.c
Update copyright year to 2015
[gnu-emacs] / src / process.c
index 4449493a2b6e4e446bf77162a478f96f01de43a7..6eb0f9e2ab47be9fa30afea067ec731610c2d0a0 100644 (file)
@@ -1,7 +1,7 @@
 /* Asynchronous subprocess control for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2014
-  Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2015 Free Software
+Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -173,6 +173,9 @@ close_on_exec (int fd)
   return fd;
 }
 
+# undef accept4
+# define accept4(sockfd, addr, addrlen, flags) \
+    process_accept4 (sockfd, addr, addrlen, flags)
 static int
 accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
 {
@@ -323,10 +326,10 @@ static int max_process_desc;
 /* The largest descriptor currently in use for input; -1 if none.  */
 static int max_input_desc;
 
-/* Indexed by descriptor, gives the process (if any) for that descriptor */
+/* Indexed by descriptor, gives the process (if any) for that descriptor */
 static Lisp_Object chan_process[FD_SETSIZE];
 
-/* Alist of elements (NAME . PROCESS) */
+/* Alist of elements (NAME . PROCESS) */
 static Lisp_Object Vprocess_alist;
 
 /* Buffered-ahead input char from process, indexed by channel.
@@ -453,7 +456,7 @@ static struct fd_callback_data
   void *data;
 #define FOR_READ  1
 #define FOR_WRITE 2
-  int condition; /* mask of the defines above.  */
+  int condition; /* Mask of the defines above.  */
 } fd_callback_info[FD_SETSIZE];
 
 
@@ -596,7 +599,7 @@ status_message (struct Lisp_Process *p)
   Lisp_Object symbol;
   int code;
   bool coredump;
-  Lisp_Object string, string2;
+  Lisp_Object string;
 
   decode_status (status, &symbol, &code, &coredump);
 
@@ -620,8 +623,8 @@ status_message (struct Lisp_Process *p)
          if (c1 != c2)
            Faset (string, make_number (0), make_number (c2));
        }
-      string2 = build_string (coredump ? " (core dumped)\n" : "\n");
-      return concat2 (string, string2);
+      AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n");
+      return concat2 (string, suffix);
     }
   else if (EQ (symbol, Qexit))
     {
@@ -629,17 +632,17 @@ status_message (struct Lisp_Process *p)
        return build_string (code == 0 ? "deleted\n" : "connection broken by remote peer\n");
       if (code == 0)
        return build_string ("finished\n");
+      AUTO_STRING (prefix, "exited abnormally with code ");
       string = Fnumber_to_string (make_number (code));
-      string2 = build_string (coredump ? " (core dumped)\n" : "\n");
-      return concat3 (build_string ("exited abnormally with code "),
-                     string, string2);
+      AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n");
+      return concat3 (prefix, string, suffix);
     }
   else if (EQ (symbol, Qfailed))
     {
+      AUTO_STRING (prefix, "failed with code ");
       string = Fnumber_to_string (make_number (code));
-      string2 = build_string ("\n");
-      return concat3 (build_string ("failed with code "),
-                     string, string2);
+      AUTO_STRING (suffix, "\n");
+      return concat3 (prefix, string, suffix);
     }
   else
     return Fcopy_sequence (Fsymbol_name (symbol));
@@ -688,8 +691,8 @@ allocate_pty (char pty_name[PTY_NAME_SIZE])
               have a race condition between the PTY_OPEN and here.  */
            fcntl (fd, F_SETFD, FD_CLOEXEC);
 #endif
-           /* check to make certain that both sides are available
-              this avoids a nasty yet stupid bug in rlogins */
+           /* Check to make certain that both sides are available
+              this avoids a nasty yet stupid bug in rlogins */
 #ifdef PTY_TTY_NAME_SPRINTF
            PTY_TTY_NAME_SPRINTF
 #else
@@ -1302,30 +1305,34 @@ Returns nil if format of ADDRESS is invalid.  */)
       ptrdiff_t size = p->header.size;
       Lisp_Object args[10];
       int nargs, i;
+      char const *format;
 
       if (size == 4 || (size == 5 && !NILP (omit_port)))
        {
-         args[0] = build_string ("%d.%d.%d.%d");
+         format = "%d.%d.%d.%d";
          nargs = 4;
        }
       else if (size == 5)
        {
-         args[0] = build_string ("%d.%d.%d.%d:%d");
+         format = "%d.%d.%d.%d:%d";
          nargs = 5;
        }
       else if (size == 8 || (size == 9 && !NILP (omit_port)))
        {
-         args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+         format = "%x:%x:%x:%x:%x:%x:%x:%x";
          nargs = 8;
        }
       else if (size == 9)
        {
-         args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d");
+         format = "[%x:%x:%x:%x:%x:%x:%x:%x]:%d";
          nargs = 9;
        }
       else
        return Qnil;
 
+      AUTO_STRING (format_obj, format);
+      args[0] = format_obj;
+
       for (i = 0; i < nargs; i++)
        {
          if (! RANGED_INTEGERP (0, p->contents[i], 65535))
@@ -1336,18 +1343,16 @@ Returns nil if format of ADDRESS is invalid.  */)
              && XINT (p->contents[i]) > 255)
            return Qnil;
 
-         args[i+1] = p->contents[i];
+         args[i + 1] = p->contents[i];
        }
 
-      return Fformat (nargs+1, args);
+      return Fformat (nargs + 1, args);
     }
 
   if (CONSP (address))
     {
-      Lisp_Object args[2];
-      args[0] = build_string ("<Family %d>");
-      args[1] = Fcar (address);
-      return Fformat (2, args);
+      AUTO_STRING (format, "<Family %d>");
+      return Fformat (2, (Lisp_Object []) {format, Fcar (address)});
     }
 
   return Qnil;
@@ -1386,9 +1391,10 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object buffer, name, program, proc, current_dir, tem;
-  register unsigned char **new_argv;
+  unsigned char **new_argv;
   ptrdiff_t i;
   ptrdiff_t count = SPECPDL_INDEX ();
+  USE_SAFE_ALLOCA;
 
   buffer = args[1];
   if (!NILP (buffer))
@@ -1464,7 +1470,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
     val = Vcoding_system_for_read;
     if (NILP (val))
       {
-       args2 = alloca ((nargs + 1) * sizeof *args2);
+       SAFE_ALLOCA_LISP (args2, nargs + 1);
        args2[0] = Qstart_process;
        for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
        GCPRO2 (proc, current_dir);
@@ -1483,7 +1489,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
       {
        if (EQ (coding_systems, Qt))
          {
-           args2 = alloca ((nargs + 1) * sizeof *args2);
+           SAFE_ALLOCA_LISP (args2, nargs + 1);
            args2[0] = Qstart_process;
            for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
            GCPRO2 (proc, current_dir);
@@ -1578,7 +1584,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
       /* Now that everything is encoded we can collect the strings into
         NEW_ARGV.  */
-      new_argv = alloca ((nargs - 1) * sizeof *new_argv);
+      SAFE_NALLOCA (new_argv, 1, nargs - 1);
       new_argv[nargs - 2] = 0;
 
       for (i = nargs - 2; i-- != 0; )
@@ -1592,6 +1598,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
   else
     create_pty (proc);
 
+  SAFE_FREE ();
   return unbind_to (count, proc);
 }
 
@@ -1716,7 +1723,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   if (inchannel > max_process_desc)
     max_process_desc = inchannel;
 
-  /* This may signal an error. */
+  /* This may signal an error.  */
   setup_process_coding_systems (process);
 
   block_input ();
@@ -1989,7 +1996,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
       {
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
        uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr;
-       len = sizeof (sin6->sin6_addr)/2 + 1;
+       len = sizeof (sin6->sin6_addr) / 2 + 1;
        address = Fmake_vector (make_number (len), Qnil);
        p = XVECTOR (address);
        p->contents[--len] = make_number (ntohs (sin6->sin6_port));
@@ -2071,8 +2078,10 @@ get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
           && VECTORP (XCDR (address)))
     {
       struct sockaddr *sa;
-      *familyp = XINT (XCAR (address));
       p = XVECTOR (XCDR (address));
+      if (MAX_ALLOCA - sizeof sa->sa_family < p->header.size)
+       return 0;
+      *familyp = XINT (XCAR (address));
       return p->header.size + sizeof (sa->sa_family);
     }
   return 0;
@@ -2198,14 +2207,14 @@ Returns nil upon error setting address, ADDRESS otherwise.  */)
 
 static const struct socket_options {
   /* The name of this option.  Should be lowercase version of option
-     name without SO_ prefix. */
+     name without SO_ prefix.  */
   const char *name;
-  /* Option level SOL_... */
+  /* Option level SOL_...  */
   int optlevel;
-  /* Option number SO_... */
+  /* Option number SO_...  */
   int optnum;
   enum { SOPT_UNKNOWN, SOPT_BOOL, SOPT_INT, SOPT_IFNAME, SOPT_LINGER } opttype;
-  enum { OPIX_NONE=0, OPIX_MISC=1, OPIX_REUSEADDR=2 } optbit;
+  enum { OPIX_NONE = 0, OPIX_MISC = 1, OPIX_REUSEADDR = 2 } optbit;
 } socket_options[] =
   {
 #ifdef SO_BINDTODEVICE
@@ -2281,7 +2290,7 @@ set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
 #ifdef SO_BINDTODEVICE
     case SOPT_IFNAME:
       {
-       char devname[IFNAMSIZ+1];
+       char devname[IFNAMSIZ + 1];
 
        /* This is broken, at least in the Linux 2.4 kernel.
           To unbind, the arg must be a zero integer, not the empty string.
@@ -2658,7 +2667,7 @@ usage:  (make-serial-process &rest ARGS)  */)
    exactly like a normal process when reading and writing.  Primary
    differences are in status display and process deletion.  A network
    connection has no PID; you cannot signal it.  All you can do is
-   stop/continue it and deactivate/close it via delete-process */
+   stop/continue it and deactivate/close it via delete-process */
 
 DEFUN ("make-network-process", Fmake_network_process, Smake_network_process,
        0, MANY, 0,
@@ -2862,7 +2871,7 @@ usage: (make-network-process &rest ARGS)  */)
   GCPRO1 (contact);
 
 #ifdef WINDOWSNT
-  /* Ensure socket support is loaded if available. */
+  /* Ensure socket support is loaded if available.  */
   init_winsock (TRUE);
 #endif
 
@@ -2969,7 +2978,7 @@ usage: (make-network-process &rest ARGS)  */)
     {
       if (EQ (host, Qlocal))
        /* Depending on setup, "localhost" may map to different IPv4 and/or
-          IPv6 addresses, so it's better to be explicit.  (Bug#6781) */
+          IPv6 addresses, so it's better to be explicit (Bug#6781).  */
        host = build_string ("127.0.0.1");
       CHECK_STRING (host);
     }
@@ -2989,7 +2998,7 @@ usage: (make-network-process &rest ARGS)  */)
       address_un.sun_family = AF_LOCAL;
       if (sizeof address_un.sun_path <= SBYTES (service))
        error ("Service name too long");
-      strcpy (address_un.sun_path, SSDATA (service));
+      lispstpcpy (address_un.sun_path, service);
       ai.ai_addr = (struct sockaddr *) &address_un;
       ai.ai_addrlen = sizeof address_un;
       goto open_socket;
@@ -3101,7 +3110,7 @@ usage: (make-network-process &rest ARGS)  */)
          address_in.sin_family = family;
        }
       else
-       /* Attempt to interpret host as numeric inet address */
+       /* Attempt to interpret host as numeric inet address */
        {
          unsigned long numeric_addr;
          numeric_addr = inet_addr (SSDATA (host));
@@ -3167,8 +3176,8 @@ 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.  */
-      for (optn = optbits = 0; optn < nargs-1; optn += 2)
-       optbits |= set_socket_option (s, args[optn], args[optn+1]);
+      for (optn = optbits = 0; optn < nargs - 1; optn += 2)
+       optbits |= set_socket_option (s, args[optn], args[optn + 1]);
 
       if (is_server)
        {
@@ -3239,7 +3248,7 @@ usage: (make-network-process &rest ARGS)  */)
        {
          /* Unlike most other syscalls connect() cannot be called
             again.  (That would return EALREADY.)  The proper way to
-            wait for completion is pselect(). */
+            wait for completion is pselect().  */
          int sc;
          socklen_t len;
          fd_set fdset;
@@ -3617,7 +3626,7 @@ static const struct ifflag_def ifflag_table[] = {
 #endif
 #ifdef IFF_NOTRAILERS
 #ifdef NS_IMPL_COCOA
-  /* Really means smart, notrailers is obsolete */
+  /* Really means smart, notrailers is obsolete */
   { IFF_NOTRAILERS,    "smart" },
 #else
   { IFF_NOTRAILERS,    "notrailers" },
@@ -3645,19 +3654,19 @@ static const struct ifflag_def ifflag_table[] = {
   { IFF_DYNAMIC,       "dynamic" },
 #endif
 #ifdef IFF_OACTIVE
-  { IFF_OACTIVE,       "oactive" },    /* OpenBSD: transmission in progress */
+  { IFF_OACTIVE,       "oactive" }, /* OpenBSD: transmission in progress.  */
 #endif
 #ifdef IFF_SIMPLEX
-  { IFF_SIMPLEX,       "simplex" },    /* OpenBSD: can't hear own transmissions */
+  { IFF_SIMPLEX,       "simplex" }, /* OpenBSD: can't hear own transmissions.  */
 #endif
 #ifdef IFF_LINK0
-  { IFF_LINK0,         "link0" },      /* OpenBSD: per link layer defined bit */
+  { IFF_LINK0,         "link0" }, /* OpenBSD: per link layer defined bit.  */
 #endif
 #ifdef IFF_LINK1
-  { IFF_LINK1,         "link1" },      /* OpenBSD: per link layer defined bit */
+  { IFF_LINK1,         "link1" }, /* OpenBSD: per link layer defined bit.  */
 #endif
 #ifdef IFF_LINK2
-  { IFF_LINK2,         "link2" },      /* OpenBSD: per link layer defined bit */
+  { IFF_LINK2,         "link2" }, /* OpenBSD: per link layer defined bit.  */
 #endif
   { 0, 0 }
 };
@@ -3680,7 +3689,7 @@ network_interface_info (Lisp_Object ifname)
 
   if (sizeof rq.ifr_name <= SBYTES (ifname))
     error ("interface name too long");
-  strcpy (rq.ifr_name, SSDATA (ifname));
+  lispstpcpy (rq.ifr_name, ifname);
 
   s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
   if (s < 0)
@@ -3873,7 +3882,7 @@ deactivate_process (Lisp_Object proc)
     }
 #endif
 
-  /* Beware SIGCHLD hereabouts. */
+  /* Beware SIGCHLD hereabouts.  */
 
   for (i = 0; i < PROCESS_OPEN_FDS; i++)
     close_process_fd (&p->open_fd[i]);
@@ -3988,10 +3997,10 @@ is nil, from any process) before the timeout expired.  */)
 
   return
     ((wait_reading_process_output (secs, nsecs, 0, 0,
-                                 Qnil,
-                                 !NILP (process) ? XPROCESS (process) : NULL,
-                                 NILP (just_this_one) ? 0 :
-                                 !INTEGERP (just_this_one) ? 1 : -1)
+                                  Qnil,
+                                  !NILP (process) ? XPROCESS (process) : NULL,
+                                  (NILP (just_this_one) ? 0
+                                   : !INTEGERP (just_this_one) ? 1 : -1))
       <= 0)
      ? Qnil : Qt);
 }
@@ -4005,7 +4014,7 @@ server_accept_connection (Lisp_Object server, int channel)
 {
   Lisp_Object proc, caller, name, buffer;
   Lisp_Object contact, host, service;
-  struct Lisp_Process *ps= XPROCESS (server);
+  struct Lisp_Process *ps = XPROCESS (server);
   struct Lisp_Process *p;
   int s;
   union u_sockaddr {
@@ -4057,20 +4066,15 @@ server_accept_connection (Lisp_Object server, int channel)
     {
     case AF_INET:
       {
-       Lisp_Object args[5];
        unsigned char *ip = (unsigned char *)&saddr.in.sin_addr.s_addr;
-       args[0] = build_string ("%d.%d.%d.%d");
-       args[1] = make_number (*ip++);
-       args[2] = make_number (*ip++);
-       args[3] = make_number (*ip++);
-       args[4] = make_number (*ip++);
-       host = Fformat (5, args);
-       service = make_number (ntohs (saddr.in.sin_port));
 
-       args[0] = build_string (" <%s:%d>");
-       args[1] = host;
-       args[2] = service;
-       caller = Fformat (3, args);
+       AUTO_STRING (ipv4_format, "%d.%d.%d.%d");
+       host = Fformat (5, ((Lisp_Object [])
+         { ipv4_format, make_number (ip[0]),
+           make_number (ip[1]), make_number (ip[2]), make_number (ip[3]) }));
+       service = make_number (ntohs (saddr.in.sin_port));
+       AUTO_STRING (caller_format, " <%s:%d>");
+       caller = Fformat (3, (Lisp_Object []) {caller_format, host, service});
       }
       break;
 
@@ -4080,16 +4084,15 @@ server_accept_connection (Lisp_Object server, int channel)
        Lisp_Object args[9];
        uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr;
        int i;
-       args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+
+       AUTO_STRING (ipv6_format, "%x:%x:%x:%x:%x:%x:%x:%x");
+       args[0] = ipv6_format;
        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));
-
-       args[0] = build_string (" <[%s]:%d>");
-       args[1] = host;
-       args[2] = service;
-       caller = Fformat (3, args);
+       AUTO_STRING (caller_format, " <[%s]:%d>");
+       caller = Fformat (3, (Lisp_Object []) {caller_format, host, service});
       }
       break;
 #endif
@@ -4099,7 +4102,9 @@ server_accept_connection (Lisp_Object server, int channel)
 #endif
     default:
       caller = Fnumber_to_string (make_number (connect_counter));
-      caller = concat3 (build_string (" <"), caller, build_string (">"));
+      AUTO_STRING (space_less_than, " <");
+      AUTO_STRING (greater_than, ">");
+      caller = concat3 (space_less_than, caller, greater_than);
       break;
     }
 
@@ -4196,16 +4201,18 @@ server_accept_connection (Lisp_Object server, int channel)
   p->inherit_coding_system_flag
     = (NILP (buffer) ? 0 : ps->inherit_coding_system_flag);
 
+  AUTO_STRING (dash, "-");
+  AUTO_STRING (nl, "\n");
+  Lisp_Object host_string = STRINGP (host) ? host : dash;
+
   if (!NILP (ps->log))
-      call3 (ps->log, server, proc,
-            concat3 (build_string ("accept from "),
-                     (STRINGP (host) ? host : build_string ("-")),
-                     build_string ("\n")));
+    {
+      AUTO_STRING (accept_from, "accept from ");
+      call3 (ps->log, server, proc, concat3 (accept_from, host_string, nl));
+    }
 
-  exec_sentinel (proc,
-                concat3 (build_string ("open from "),
-                         (STRINGP (host) ? host : build_string ("-")),
-                         build_string ("\n")));
+  AUTO_STRING (open_from, "open from ");
+  exec_sentinel (proc, concat3 (open_from, host_string, nl));
 }
 
 /* This variable is different from waiting_for_input in keyboard.c.
@@ -4316,7 +4323,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
   while (1)
     {
-      bool timeout_reduced_for_timers = 0;
+      bool timeout_reduced_for_timers = false;
 
       /* If calling from keyboard input, do not quit
         since we want to return C-g as an input character.
@@ -4340,7 +4347,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
        {
          /* A negative timeout means
             gobble output available now
-            but don't wait at all. */
+            but don't wait at all.  */
 
          timeout = make_timespec (0, 0);
        }
@@ -4403,7 +4410,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                  if (timespec_cmp (timer_delay, timeout) < 0)
                    {
                      timeout = timer_delay;
-                     timeout_reduced_for_timers = 1;
+                     timeout_reduced_for_timers = true;
                    }
                }
              else
@@ -4466,7 +4473,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
          && ! EQ (wait_proc->status, Qrun)
          && ! EQ (wait_proc->status, Qconnect))
        {
-         bool read_some_bytes = 0;
+         bool read_some_bytes = false;
 
          clear_waiting_for_input ();
          XSETPROCESS (proc, wait_proc);
@@ -4499,11 +4506,11 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
          break;
        }
 
-      /* Wait till there is something to do */
+      /* Wait till there is something to do */
 
       if (wait_proc && just_wait_proc)
        {
-         if (wait_proc->infd < 0)  /* Terminated */
+         if (wait_proc->infd < 0)  /* Terminated */
            break;
          FD_SET (wait_proc->infd, &Available);
          check_delay = 0;
@@ -4634,7 +4641,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                }
              else
                {
-                 /* Check this specific channel. */
+                 /* Check this specific channel.  */
                  if (wait_proc->gnutls_p /* Check for valid process.  */
                      && wait_proc->gnutls_state
                      /* Do we have pending data?  */
@@ -4654,7 +4661,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
       xerrno = errno;
 
-      /* Make C-g and alarm signals set flags again */
+      /* Make C-g and alarm signals set flags again */
       clear_waiting_for_input ();
 
       /*  If we woke up due to SIGWINCH, actually change size now.  */
@@ -4673,22 +4680,22 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
            report_file_errno ("Failed select", Qnil, xerrno);
        }
 
-      /* Check for keyboard input */
+      /* Check for keyboard input */
       /* If there is any, return immediately
-        to give it higher priority than subprocesses */
+        to give it higher priority than subprocesses */
 
       if (read_kbd != 0)
        {
          unsigned old_timers_run = timers_run;
          struct buffer *old_buffer = current_buffer;
          Lisp_Object old_window = selected_window;
-         bool leave = 0;
+         bool leave = false;
 
          if (detect_input_pending_run_timers (do_display))
            {
              swallow_events (do_display);
              if (detect_input_pending_run_timers (do_display))
-               leave = 1;
+               leave = true;
            }
 
          /* If a timer has run, this might have changed buffers
@@ -4973,18 +4980,17 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars,
    for decoding.  */
 
 static int
-read_process_output (Lisp_Object proc, register int channel)
+read_process_output (Lisp_Object proc, int channel)
 {
-  register ssize_t nbytes;
-  char *chars;
-  register struct Lisp_Process *p = XPROCESS (proc);
+  ssize_t nbytes;
+  struct Lisp_Process *p = XPROCESS (proc);
   struct coding_system *coding = proc_decode_coding_system[channel];
   int carryover = p->decoding_carryover;
-  int readmax = 4096;
+  enum { readmax = 4096 };
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object odeactivate;
+  char chars[sizeof coding->carryover + readmax];
 
-  chars = alloca (carryover + readmax);
   if (carryover)
     /* See the comment above.  */
     memcpy (chars, SDATA (p->decoding_buf), carryover);
@@ -5685,7 +5691,7 @@ return t unconditionally.  */)
   return Qt;
 }
 \f
-/* send a signal number SIGNO to PROCESS.
+/* Send a signal number SIGNO to PROCESS.
    If CURRENT_GROUP is t, that means send to the process group
    that currently owns the terminal being used to communicate with PROCESS.
    This is used for various commands in shell mode.
@@ -5788,11 +5794,11 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
         Or perhaps this is vestigial.  */
       if (gid == -1)
        no_pgrp = 1;
-#else  /* ! defined (TIOCGPGRP ) */
+#else  /* ! defined (TIOCGPGRP) */
       /* Can't select pgrps on this system, so we know that
         the child itself heads the pgrp.  */
       gid = p->pid;
-#endif /* ! defined (TIOCGPGRP ) */
+#endif /* ! defined (TIOCGPGRP) */
 
       /* If current_group is lambda, and the shell owns the terminal,
         don't send any signal.  */
@@ -5974,8 +5980,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
       Lisp_Object tem = Fget_process (process);
       if (NILP (tem))
        {
-         Lisp_Object process_number =
-           string_to_number (SSDATA (process), 10, 1);
+         Lisp_Object process_number
+           string_to_number (SSDATA (process), 10, 1);
          if (INTEGERP (process_number) || FLOATP (process_number))
            tem = process_number;
        }
@@ -6158,7 +6164,7 @@ static signal_handler_t volatile lib_child_handler;
    Inc.
 
    ** Malloc WARNING: This should never call malloc either directly or
-   indirectly; if it does, that is a bug  */
+   indirectly; if it does, that is a bug.  */
 
 static void
 handle_child_signal (int sig)
@@ -6231,7 +6237,7 @@ handle_child_signal (int sig)
 #ifdef NS_IMPL_GNUSTEP
   /* NSTask in GNUstep sets its child handler each time it is called.
      So we must re-set ours.  */
-  catch_child_signal();
+  catch_child_signal ();
 #endif
 }
 
@@ -6595,7 +6601,7 @@ keyboard_bit_set (fd_set *mask)
 
 #else  /* not subprocesses */
 
-/* Defined on msdos.c.  */
+/* Defined in msdos.c.  */
 extern int sys_select (int, fd_set *, fd_set *, fd_set *,
                       struct timespec *, void *);
 
@@ -6663,7 +6669,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
   while (1)
     {
-      bool timeout_reduced_for_timers = 0;
+      bool timeout_reduced_for_timers = false;
       fd_set waitchannels;
       int xerrno;
 
@@ -6730,7 +6736,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              if (timespec_cmp (timer_delay, timeout) < 0)
                {
                  timeout = timer_delay;
-                 timeout_reduced_for_timers = 1;
+                 timeout_reduced_for_timers = true;
                }
            }
        }
@@ -6763,7 +6769,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
       xerrno = errno;
 
-      /* Make C-g and alarm signals set flags again */
+      /* Make C-g and alarm signals set flags again */
       clear_waiting_for_input ();
 
       /*  If we woke up due to SIGWINCH, actually change size now.  */
@@ -6783,7 +6789,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
            report_file_errno ("Failed select", Qnil, xerrno);
        }
 
-      /* Check for keyboard input */
+      /* Check for keyboard input */
 
       if (read_kbd
          && detect_input_pending_run_timers (do_display))
@@ -6827,12 +6833,32 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 /* The following functions are needed even if async subprocesses are
    not supported.  Some of them are no-op stubs in that case.  */
 
+#ifdef HAVE_TIMERFD
+
+/* Add FD, which is a descriptor returned by timerfd_create,
+   to the set of non-keyboard input descriptors.  */
+
+void
+add_timer_wait_descriptor (int fd)
+{
+  FD_SET (fd, &input_wait_mask);
+  FD_SET (fd, &non_keyboard_wait_mask);
+  FD_SET (fd, &non_process_wait_mask);
+  fd_callback_info[fd].func = timerfd_callback;
+  fd_callback_info[fd].data = NULL;
+  fd_callback_info[fd].condition |= FOR_READ;
+  if (fd > max_input_desc)
+    max_input_desc = fd;
+}
+
+#endif /* HAVE_TIMERFD */
+
 /* Add DESC to the set of keyboard input descriptors.  */
 
 void
 add_keyboard_wait_descriptor (int desc)
 {
-#ifdef subprocesses /* actually means "not MSDOS" */
+#ifdef subprocesses /* Actually means "not MSDOS".  */
   FD_SET (desc, &input_wait_mask);
   FD_SET (desc, &non_process_wait_mask);
   if (desc > max_input_desc)
@@ -6923,7 +6949,7 @@ the process output.  */)
 }
 
 /* Kill all processes associated with `buffer'.
-   If `buffer' is nil, kill all processes  */
+   If `buffer' is nil, kill all processes.  */
 
 void
 kill_buffer_processes (Lisp_Object buffer)
@@ -7066,7 +7092,8 @@ catch_child_signal (void)
   emacs_sigaction_init (&action, deliver_child_signal);
   block_child_signal (&oldset);
   sigaction (SIGCHLD, &action, &old_action);
-  eassert (! (old_action.sa_flags & SA_SIGINFO));
+  eassert (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN
+          || ! (old_action.sa_flags & SA_SIGINFO));
 
   if (old_action.sa_handler != deliver_child_signal)
     lib_child_handler