Remove configure's --without-sync-input option.
[bpt/emacs.git] / src / sysdep.c
index 089b7ba..dbfd9ef 100644 (file)
@@ -18,10 +18,11 @@ You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
-#include <ctype.h>
-#include <signal.h>
+
+#define SYSTIME_INLINE EXTERN_INLINE
+
+#include <execinfo.h>
 #include <stdio.h>
-#include <setjmp.h>
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #include <grp.h>
@@ -30,6 +31,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <unistd.h>
 
 #include <allocator.h>
+#include <c-ctype.h>
 #include <careadlinkat.h>
 #include <ignore-value.h>
 #include <utimens.h>
@@ -38,17 +40,17 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "sysselect.h"
 #include "blockinput.h"
 
-#ifdef __FreeBSD__
+#ifdef BSD_SYSTEM
+#include <sys/param.h>
 #include <sys/sysctl.h>
+#endif
+
+#ifdef __FreeBSD__
 #include <sys/user.h>
 #include <sys/resource.h>
 #include <math.h>
 #endif
 
-#ifdef DARWIN_OS
-#include <sys/sysctl.h>
-#endif
-
 #ifdef WINDOWSNT
 #define read sys_read
 #define write sys_write
@@ -65,8 +67,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
-#include <dos.h>
-#include "dosfns.h"
 #include "msdos.h"
 #include <sys/param.h>
 #endif
@@ -106,8 +106,10 @@ extern char *getwd (char *);
 
 static int emacs_get_tty (int, struct emacs_tty *);
 static int emacs_set_tty (int, struct emacs_tty *, int);
-#if defined TIOCNOTTY || defined USG5 || defined CYGWIN
-static _Noreturn void croak (char *);
+
+/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781.  */
+#ifndef ULLONG_MAX
+#define ULLONG_MAX TYPE_MAXIMUM (unsigned long long int)
 #endif
 
 /* Declare here, including term.h is problematic on some systems.  */
@@ -145,7 +147,7 @@ get_current_dir_name (void)
 #endif
       )
     {
-      buf = (char *) malloc (strlen (pwd) + 1);
+      buf = malloc (strlen (pwd) + 1);
       if (!buf)
         return NULL;
       strcpy (buf, pwd);
@@ -154,7 +156,7 @@ get_current_dir_name (void)
   else
     {
       size_t buf_size = 1024;
-      buf = (char *) malloc (buf_size);
+      buf = malloc (buf_size);
       if (!buf)
         return NULL;
       for (;;)
@@ -169,7 +171,7 @@ get_current_dir_name (void)
               return NULL;
             }
           buf_size *= 2;
-          buf = (char *) realloc (buf, buf_size);
+          buf = realloc (buf, buf_size);
           if (!buf)
             return NULL;
         }
@@ -178,7 +180,7 @@ get_current_dir_name (void)
   else
     {
       /* We need MAXPATHLEN here.  */
-      buf = (char *) malloc (MAXPATHLEN + 1);
+      buf = malloc (MAXPATHLEN + 1);
       if (!buf)
         return NULL;
       if (getwd (buf) == NULL)
@@ -291,32 +293,39 @@ wait_for_termination_1 (pid_t pid, int interruptible)
 #if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined (__GNU__)
       /* Note that kill returns -1 even if the process is just a zombie now.
         But inevitably a SIGCHLD interrupt should be generated
-        and child_sig will do wait3 and make the process go away. */
+        and child_sig will do waitpid and make the process go away.  */
       /* There is some indication that there is a bug involved with
         termination of subprocesses, perhaps involving a kernel bug too,
         but no idea what it is.  Just as a hunch we signal SIGCHLD to see
         if that causes the problem to go away or get worse.  */
-      sigsetmask (sigmask (SIGCHLD));
+      sigset_t sigchild_mask;
+      sigemptyset (&sigchild_mask);
+      sigaddset (&sigchild_mask, SIGCHLD);
+      pthread_sigmask (SIG_SETMASK, &sigchild_mask, 0);
+
       if (0 > kill (pid, 0))
        {
-         sigsetmask (SIGEMPTYMASK);
+         pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
          kill (getpid (), SIGCHLD);
          break;
        }
       if (wait_debugging)
        sleep (1);
       else
-       sigpause (SIGEMPTYMASK);
+       sigsuspend (&empty_mask);
 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
 #ifdef WINDOWSNT
       wait (0);
       break;
 #else /* not WINDOWSNT */
-      sigblock (sigmask (SIGCHLD));
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGCHLD);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
       errno = 0;
       if (kill (pid, 0) == -1 && errno == ESRCH)
        {
-         sigunblock (sigmask (SIGCHLD));
+         pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
          break;
        }
 
@@ -450,11 +459,11 @@ child_setup_tty (int out)
 #endif /* not MSDOS */
 
 \f
-/* Record a signal code and the handler for it.  */
+/* Record a signal code and the action for it.  */
 struct save_signal
 {
   int code;
-  void (*handler) (int);
+  struct sigaction action;
 };
 
 static void save_signal_handlers (struct save_signal *);
@@ -500,7 +509,7 @@ sys_subshell (void)
   saved_handlers[0].code = SIGINT;
   saved_handlers[1].code = SIGQUIT;
   saved_handlers[2].code = SIGTERM;
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
   saved_handlers[3].code = SIGIO;
   saved_handlers[4].code = 0;
 #else
@@ -518,7 +527,7 @@ sys_subshell (void)
     goto xyzzy;
 
   dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
-  str_volatile = str = (unsigned char *) alloca (SCHARS (dir) + 2);
+  str_volatile = str = alloca (SCHARS (dir) + 2);
   len = SCHARS (dir);
   memcpy (str, SDATA (dir), len);
   if (str[len - 1] != '/') str[len++] = '/';
@@ -612,8 +621,9 @@ save_signal_handlers (struct save_signal *saved_handlers)
 {
   while (saved_handlers->code)
     {
-      saved_handlers->handler
-        = (void (*) (int)) signal (saved_handlers->code, SIG_IGN);
+      struct sigaction action;
+      emacs_sigaction_init (&action, SIG_IGN);
+      sigaction (saved_handlers->code, &action, &saved_handlers->action);
       saved_handlers++;
     }
 }
@@ -623,118 +633,80 @@ restore_signal_handlers (struct save_signal *saved_handlers)
 {
   while (saved_handlers->code)
     {
-      signal (saved_handlers->code, saved_handlers->handler);
+      sigaction (saved_handlers->code, &saved_handlers->action, 0);
       saved_handlers++;
     }
 }
 \f
-#ifndef SIGIO
-/* If SIGIO is broken, don't do anything. */
-void
-init_sigio (int fd)
-{
-}
-
-static void
-reset_sigio (int fd)
-{
-}
-
-void
-request_sigio (void)
-{
-}
-
-void
-unrequest_sigio (void)
-{
-}
-
-#else
-#ifdef F_SETFL
-
+#ifdef USABLE_SIGIO
 static int old_fcntl_flags[MAXDESC];
+#endif
 
 void
 init_sigio (int fd)
 {
-#ifdef FASYNC
+#ifdef USABLE_SIGIO
   old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
   fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
-#endif
   interrupts_deferred = 0;
+#endif
 }
 
 static void
 reset_sigio (int fd)
 {
-#ifdef FASYNC
+#ifdef USABLE_SIGIO
   fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
 #endif
 }
 
-#ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
-/* XXX Uhm, FASYNC is not used anymore here. */
-/* XXX Yeah, but you need it for SIGIO, don't you? */
-
 void
 request_sigio (void)
 {
+#ifdef USABLE_SIGIO
+  sigset_t unblocked;
+
   if (noninteractive)
     return;
 
-#ifdef SIGWINCH
-  sigunblock (sigmask (SIGWINCH));
-#endif
-  sigunblock (sigmask (SIGIO));
+  sigemptyset (&unblocked);
+# ifdef SIGWINCH
+  sigaddset (&unblocked, SIGWINCH);
+# endif
+  sigaddset (&unblocked, SIGIO);
+  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
 
   interrupts_deferred = 0;
+#endif
 }
 
 void
 unrequest_sigio (void)
 {
-  if (noninteractive)
-    return;
+#ifdef USABLE_SIGIO
+  sigset_t blocked;
 
-#if 0 /* XXX What's wrong with blocking SIGIO under X?  */
-  if (x_display_list)
+  if (noninteractive)
     return;
-#endif
 
-#ifdef SIGWINCH
-  sigblock (sigmask (SIGWINCH));
-#endif
-  sigblock (sigmask (SIGIO));
+  sigemptyset (&blocked);
+# ifdef SIGWINCH
+  sigaddset (&blocked, SIGWINCH);
+# endif
+  sigaddset (&blocked, SIGIO);
+  pthread_sigmask (SIG_BLOCK, &blocked, 0);
   interrupts_deferred = 1;
+#endif
 }
 
-#else /* no FASYNC */
-#ifndef MSDOS
-
 void
-request_sigio (void)
+ignore_sigio (void)
 {
-  if (noninteractive || read_socket_hook)
-    return;
-
-  croak ("request_sigio");
-}
-
-void
-unrequest_sigio (void)
-{
-  if (noninteractive || read_socket_hook)
-    return;
-
-  croak ("unrequest_sigio");
+#ifdef USABLE_SIGIO
+  signal (SIGIO, SIG_IGN);
+#endif
 }
 
-#endif /* MSDOS */
-#endif /* FASYNC */
-#endif /* F_SETFL */
-#endif /* SIGIO */
-
 \f
 /* Getting and setting emacs_tty structures.  */
 
@@ -853,7 +825,7 @@ init_sys_modes (struct tty_display_info *tty_out)
     return;                     /* The tty is suspended. */
 
   if (! tty_out->old_tty)
-    tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
+    tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty);
 
   emacs_get_tty (fileno (tty_out->input), tty_out->old_tty);
 
@@ -1347,7 +1319,7 @@ init_system_name (void)
   Vsystem_name = build_string (uts.nodename);
 #else /* HAVE_GETHOSTNAME */
   unsigned int hostname_size = 256;
-  char *hostname = (char *) alloca (hostname_size);
+  char *hostname = alloca (hostname_size);
 
   /* Try to get the host name; if the buffer is too short, try
      again.  Apparently, the only indication gethostname gives of
@@ -1363,7 +1335,7 @@ init_system_name (void)
        break;
 
       hostname_size <<= 1;
-      hostname = (char *) alloca (hostname_size);
+      hostname = alloca (hostname_size);
     }
 #ifdef HAVE_SOCKETS
   /* Turn the hostname into the official, fully-qualified hostname.
@@ -1464,85 +1436,64 @@ init_system_name (void)
   }
 }
 \f
-/* POSIX signals support - DJB */
-/* Anyone with POSIX signals should have ANSI C declarations */
-
 sigset_t empty_mask;
 
-#ifndef WINDOWSNT
-
-signal_handler_t
-sys_signal (int signal_number, signal_handler_t action)
+/* Store into *ACTION a signal action suitable for Emacs, with handler
+   HANDLER.  */
+void
+emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
 {
-  struct sigaction new_action, old_action;
-  sigemptyset (&new_action.sa_mask);
-  new_action.sa_handler = action;
-  new_action.sa_flags = 0;
+  sigemptyset (&action->sa_mask);
+  action->sa_handler = handler;
+  action->sa_flags = 0;
 #if defined (SA_RESTART)
-  /* Emacs mostly works better with restartable system services. If this
-     flag exists, we probably want to turn it on here.
-     However, on some systems this resets the timeout of `select'
-     which means that `select' never finishes if it keeps getting signals.
-     BROKEN_SA_RESTART is defined on those systems.  */
-  /* It's not clear why the comment above says "mostly works better".  --Stef
-     When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
+  /* SA_RESTART causes interruptible functions with timeouts (e.g.,
+     'select') to reset their timeout on some platforms (e.g.,
+     HP-UX 11), which is not what we want.  Also, when Emacs is
+     interactive, we don't want SA_RESTART because we need to poll
      for pending input so we need long-running syscalls to be interrupted
      after a signal that sets the interrupt_input_pending flag.  */
   /* Non-interactive keyboard input goes through stdio, where we always
      want restartable system calls.  */
-# if defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
   if (noninteractive)
-# endif
-    new_action.sa_flags = SA_RESTART;
+    action->sa_flags = SA_RESTART;
 #endif
-  sigaction (signal_number, &new_action, &old_action);
-  return (old_action.sa_handler);
 }
 
-#endif /* WINDOWSNT */
-
-#ifndef __GNUC__
-/* If we're compiling with GCC, we don't need this function, since it
-   can be written as a macro.  */
-sigset_t
-sys_sigmask (int sig)
-{
-  sigset_t mask;
-  sigemptyset (&mask);
-  sigaddset (&mask, sig);
-  return mask;
-}
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+static pthread_t main_thread;
 #endif
 
-/* I'd like to have these guys return pointers to the mask storage in here,
-   but there'd be trouble if the code was saving multiple masks.  I'll be
-   safe and pass the structure.  It normally won't be more than 2 bytes
-   anyhow. - DJB */
-
-sigset_t
-sys_sigblock (sigset_t new_mask)
+/* If we are on the main thread, handle the signal SIG with HANDLER.
+   Otherwise, redirect the signal to the main thread, blocking it from
+   this thread.  POSIX says any thread can receive a signal that is
+   associated with a process, process group, or asynchronous event.
+   On GNU/Linux that is not true, but for other systems (FreeBSD at
+   least) it is.  */
+void
+handle_on_main_thread (int sig, signal_handler_t handler)
 {
-  sigset_t old_mask;
-  pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
-  return (old_mask);
-}
+  /* Preserve errno, to avoid race conditions with signal handlers that
+     might change errno.  Races can occur even in single-threaded hosts.  */
+  int old_errno = errno;
 
-sigset_t
-sys_sigunblock (sigset_t new_mask)
-{
-  sigset_t old_mask;
-  pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
-  return (old_mask);
-}
+  bool on_main_thread = true;
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+  if (! pthread_equal (pthread_self (), main_thread))
+    {
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, sig);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
+      pthread_kill (main_thread, sig);
+      on_main_thread = false;
+    }
+#endif
+  if (on_main_thread)
+    handler (sig);
 
-sigset_t
-sys_sigsetmask (sigset_t new_mask)
-{
-  sigset_t old_mask;
-  pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
-  return (old_mask);
+  errno = old_errno;
 }
-
 \f
 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
 static char *my_sys_siglist[NSIG];
@@ -1557,6 +1508,10 @@ init_signals (void)
 {
   sigemptyset (&empty_mask);
 
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+  main_thread = pthread_self ();
+#endif
+
 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
   if (! initialized)
     {
@@ -1758,19 +1713,37 @@ init_signals (void)
 #endif /* !RAND_BITS */
 
 void
-seed_random (long int arg)
+seed_random (void *seed, ptrdiff_t seed_size)
 {
+#if defined HAVE_RANDOM || ! defined HAVE_LRAND48
+  unsigned int arg = 0;
+#else
+  long int arg = 0;
+#endif
+  unsigned char *argp = (unsigned char *) &arg;
+  unsigned char *seedp = seed;
+  ptrdiff_t i;
+  for (i = 0; i < seed_size; i++)
+    argp[i % sizeof arg] ^= seedp[i];
 #ifdef HAVE_RANDOM
-  srandom ((unsigned int)arg);
+  srandom (arg);
 #else
 # ifdef HAVE_LRAND48
   srand48 (arg);
 # else
-  srand ((unsigned int)arg);
+  srand (arg);
 # endif
 #endif
 }
 
+void
+init_random (void)
+{
+  EMACS_TIME t = current_emacs_time ();
+  uintmax_t v = getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t);
+  seed_random (&v, sizeof v);
+}
+
 /*
  * Return a nonnegative random integer out of whatever we've got.
  * It contains enough bits to make a random (signed) Emacs fixnum.
@@ -1788,21 +1761,6 @@ get_random (void)
   return val & INTMASK;
 }
 
-#ifndef HAVE_STRERROR
-#ifndef WINDOWSNT
-char *
-strerror (int errnum)
-{
-  extern char *sys_errlist[];
-  extern int sys_nerr;
-
-  if (errnum >= 0 && errnum < sys_nerr)
-    return sys_errlist[errnum];
-  return (char *) "Unknown error";
-}
-#endif /* not WINDOWSNT */
-#endif /* ! HAVE_STRERROR */
-
 #ifndef HAVE_SNPRINTF
 /* Approximate snprintf as best we can on ancient hosts that lack it.  */
 int
@@ -1846,6 +1804,33 @@ snprintf (char *buf, size_t bufsize, char const *format, ...)
 }
 #endif
 \f
+/* If a backtrace is available, output the top lines of it to stderr.
+   Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines.
+   This function may be called from a signal handler, so it should
+   not invoke async-unsafe functions like malloc.  */
+void
+emacs_backtrace (int backtrace_limit)
+{
+  enum { BACKTRACE_LIMIT_MAX = 500 };
+  void *buffer[BACKTRACE_LIMIT_MAX + 1];
+  int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX);
+  int npointers = backtrace (buffer, bounded_limit + 1);
+  if (npointers)
+    ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12));
+  backtrace_symbols_fd (buffer, bounded_limit, STDERR_FILENO);
+  if (bounded_limit < npointers)
+    ignore_value (write (STDERR_FILENO, "...\n", 4));
+}
+\f
+#ifndef HAVE_NTGUI
+/* Using emacs_abort lets GDB return from a breakpoint here.  */
+void
+emacs_abort (void)
+{
+  fatal_error_backtrace (SIGABRT, 10);
+}
+#endif
+
 int
 emacs_open (const char *path, int oflag, int mode)
 {
@@ -1923,11 +1908,9 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
        {
          if (errno == EINTR)
            {
-#ifdef SYNC_INPUT
              /* I originally used `QUIT' but that might causes files to
                 be truncated if you hit C-g in the middle of it.  --Stef  */
              process_pending_signals ();
-#endif
              continue;
            }
          else
@@ -1979,7 +1962,7 @@ emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
  *     under error conditions.
  */
 
-#ifndef HAVE_GETWD
+#if !defined (HAVE_GETWD) || defined (BROKEN_GETWD)
 
 #ifndef MAXPATHLEN
 /* In 4.1, param.h fails to define this.  */
@@ -2009,55 +1992,7 @@ getwd (char *pathname)
   return pathname;
 }
 
-#endif /* HAVE_GETWD */
-
-/*
- *     Emulate rename using unlink/link.  Note that this is
- *     only partially correct.  Also, doesn't enforce restriction
- *     that files be of same type (regular->regular, dir->dir, etc).
- */
-
-#ifndef HAVE_RENAME
-
-int
-rename (const char *from, const char *to)
-{
-  if (access (from, 0) == 0)
-    {
-      unlink (to);
-      if (link (from, to) == 0)
-       if (unlink (from) == 0)
-         return (0);
-    }
-  return (-1);
-}
-
-#endif
-
-
-#if defined (HPUX) && !defined (HAVE_PERROR)
-
-/* HPUX curses library references perror, but as far as we know
-   it won't be called.  Anyway this definition will do for now.  */
-
-void
-perror (void)
-{
-}
-#endif /* HPUX and not HAVE_PERROR */
-
-/*
- *     This function will go away as soon as all the stubs fixed. (fnf)
- */
-
-void
-croak (char *badfunc)
-{
-  printf ("%s not yet implemented\r\n", badfunc);
-  reset_all_sys_modes ();
-  exit (1);
-}
-
+#endif /* !defined (HAVE_GETWD) || defined (BROKEN_GETWD) */
 #endif /* USG */
 \f
 /* Directory routines for systems that don't have them. */
@@ -2074,7 +2009,7 @@ closedir (DIR *dirp /* stream from opendir */)
   int rtnval;
 
   rtnval = emacs_close (dirp->dd_fd);
-  xfree ((char *) dirp);
+  xfree (dirp);
 
   return rtnval;
 }
@@ -2121,132 +2056,6 @@ set_file_times (int fd, const char *filename,
   return fdutimens (fd, filename, timespec);
 }
 \f
-/* mkdir and rmdir functions, for systems which don't have them.  */
-
-#ifndef HAVE_MKDIR
-/*
- * Written by Robert Rother, Mariah Corporation, August 1985.
- *
- * If you want it, it's yours.  All I ask in return is that if you
- * figure out how to do this in a Bourne Shell script you send me
- * a copy.
- *                                     sdcsvax!rmr or rmr@uscd
- *
- * Severely hacked over by John Gilmore to make a 4.2BSD compatible
- * subroutine.  11Mar86; hoptoad!gnu
- *
- * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
- * subroutine didn't return EEXIST.  It does now.
- */
-
-/*
- * Make a directory.
- */
-int
-mkdir (char *dpath, int dmode)
-{
-  pid_t cpid;
-  int status, fd;
-  struct stat statbuf;
-
-  if (stat (dpath, &statbuf) == 0)
-    {
-      errno = EEXIST;          /* Stat worked, so it already exists */
-      return -1;
-    }
-
-  /* If stat fails for a reason other than non-existence, return error */
-  if (errno != ENOENT)
-    return -1;
-
-  synch_process_alive = 1;
-  switch (cpid = fork ())
-    {
-
-    case -1:                   /* Error in fork */
-      return (-1);             /* Errno is set already */
-
-    case 0:                    /* Child process */
-      /*
-                * Cheap hack to set mode of new directory.  Since this
-                * child process is going away anyway, we zap its umask.
-                * FIXME, this won't suffice to set SUID, SGID, etc. on this
-                * directory.  Does anybody care?
-                */
-      status = umask (0);      /* Get current umask */
-      status = umask (status | (0777 & ~dmode));       /* Set for mkdir */
-      fd = emacs_open ("/dev/null", O_RDWR, 0);
-      if (fd >= 0)
-        {
-         dup2 (fd, 0);
-         dup2 (fd, 1);
-         dup2 (fd, 2);
-        }
-      execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
-      _exit (-1);              /* Can't exec /bin/mkdir */
-
-    default:                   /* Parent process */
-      wait_for_termination (cpid);
-    }
-
-  if (synch_process_death != 0 || synch_process_retcode != 0
-      || synch_process_termsig != 0)
-    {
-      errno = EIO;             /* We don't know why, but */
-      return -1;               /* /bin/mkdir failed */
-    }
-
-  return 0;
-}
-#endif /* not HAVE_MKDIR */
-
-#ifndef HAVE_RMDIR
-int
-rmdir (char *dpath)
-{
-  int cpid, status, fd;
-  struct stat statbuf;
-
-  if (stat (dpath, &statbuf) != 0)
-    {
-      /* Stat just set errno.  We don't have to */
-      return -1;
-    }
-
-  synch_process_alive = 1;
-  switch (cpid = fork ())
-    {
-
-    case -1:                   /* Error in fork */
-      return (-1);             /* Errno is set already */
-
-    case 0:                    /* Child process */
-      fd = emacs_open ("/dev/null", O_RDWR, 0);
-      if (fd >= 0)
-        {
-         dup2 (fd, 0);
-         dup2 (fd, 1);
-         dup2 (fd, 2);
-        }
-      execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
-      _exit (-1);              /* Can't exec /bin/rmdir */
-
-    default:                   /* Parent process */
-      wait_for_termination (cpid);
-    }
-
-  if (synch_process_death != 0 || synch_process_retcode != 0
-      || synch_process_termsig != 0)
-    {
-      errno = EIO;             /* We don't know why, but */
-      return -1;               /* /bin/rmdir failed */
-    }
-
-  return 0;
-}
-#endif /* !HAVE_RMDIR */
-
-\f
 #ifndef HAVE_STRSIGNAL
 char *
 strsignal (int code)
@@ -2476,8 +2285,7 @@ serial_configure (struct Lisp_Process *p,
     error ("tcsetattr() failed: %s", emacs_strerror (errno));
 
   childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
-  p->childp = childp2;
-
+  pset_childp (p, childp2);
 }
 #endif /* not DOS_NT  */
 \f
@@ -2522,7 +2330,7 @@ list_system_processes (void)
 Lisp_Object
 list_system_processes (void)
 {
-#ifdef DARWIN_OS
+#if defined DARWIN_OS || defined __NetBSD__ || defined __OpenBSD__
   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
 #else
   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
@@ -2548,8 +2356,10 @@ list_system_processes (void)
   len /= sizeof (struct kinfo_proc);
   for (i = 0; i < len; i++)
     {
-#ifdef DARWIN_OS
+#if defined DARWIN_OS || defined __NetBSD__
       proclist = Fcons (make_fixnum_or_float (procs[i].kp_proc.p_pid), proclist);
+#elif defined __OpenBSD__
+      proclist = Fcons (make_fixnum_or_float (procs[i].p_pid), proclist);
 #else
       proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist);
 #endif
@@ -2580,7 +2390,6 @@ time_from_jiffies (unsigned long long tval, long hz)
   unsigned long long s = tval / hz;
   unsigned long long frac = tval % hz;
   int ns;
-  EMACS_TIME t;
 
   if (TYPE_MAXIMUM (time_t) < s)
     time_overflow ();
@@ -2597,8 +2406,7 @@ time_from_jiffies (unsigned long long tval, long hz)
       ns = frac / hz_per_ns;
     }
 
-  EMACS_SET_SECS_NSECS (t, s, ns);
-  return t;
+  return make_emacs_time (s, ns);
 }
 
 static Lisp_Object
@@ -2612,9 +2420,7 @@ static EMACS_TIME
 get_up_time (void)
 {
   FILE *fup;
-  EMACS_TIME up;
-
-  EMACS_SET_SECS_NSECS (up, 0, 0);
+  EMACS_TIME up = make_emacs_time (0, 0);
 
   BLOCK_INPUT;
   fup = fopen ("/proc/uptime", "r");
@@ -2643,7 +2449,7 @@ get_up_time (void)
                upfrac /= 10;
              upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1);
            }
-         EMACS_SET_SECS_NSECS (up, upsec, upfrac);
+         up = make_emacs_time (upsec, upfrac);
        }
       fclose (fup);
     }
@@ -2738,9 +2544,11 @@ system_process_attributes (Lisp_Object pid)
   char procbuf[1025], *p, *q;
   int fd;
   ssize_t nread;
-  const char *cmd = NULL;
+  static char const default_cmd[] = "???";
+  const char *cmd = default_cmd;
+  int cmdsize = sizeof default_cmd - 1;
   char *cmdline = NULL;
-  ptrdiff_t cmdsize = 0, cmdline_size;
+  ptrdiff_t cmdline_size;
   unsigned char c;
   printmax_t proc_id;
   int ppid, pgrp, sess, tty, tpgid, thcount;
@@ -2802,11 +2610,6 @@ system_process_attributes (Lisp_Object pid)
        }
       else
        q = NULL;
-      if (cmd == NULL)
-       {
-         cmd = "???";
-         cmdsize = 3;
-       }
       /* Command name is encoded in locale-coding-system; decode it.  */
       cmd_str = make_unibyte_string (cmd, cmdsize);
       decoded_cmd = code_convert_string_norecord (cmd_str,
@@ -2871,15 +2674,15 @@ system_process_attributes (Lisp_Object pid)
          attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
          attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs);
          attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
-         EMACS_GET_TIME (tnow);
+         tnow = current_emacs_time ();
          telapsed = get_up_time ();
-         EMACS_SUB_TIME (tboot, tnow, telapsed);
+         tboot = sub_emacs_time (tnow, telapsed);
          tstart = time_from_jiffies (start, clocks_per_sec);
-         EMACS_ADD_TIME (tstart, tboot, tstart);
+         tstart = add_emacs_time (tboot, tstart);
          attrs = Fcons (Fcons (Qstart, make_lisp_time (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);
+         telapsed = sub_emacs_time (tnow, tstart);
          attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
          us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
          pcpu = (EMACS_TIME_TO_DOUBLE (us_time)
@@ -2907,7 +2710,7 @@ system_process_attributes (Lisp_Object pid)
          if (emacs_read (fd, &ch, 1) != 1)
            break;
          c = ch;
-         if (isspace (c) || c == '\\')
+         if (c_isspace (c) || c == '\\')
            cmdline_size++;     /* for later quoting, see below */
        }
       if (cmdline_size)
@@ -2931,7 +2734,7 @@ system_process_attributes (Lisp_Object pid)
          for (p = cmdline; p < cmdline + nread; p++)
            {
              /* Escape-quote whitespace and backslashes.  */
-             if (isspace (*p) || *p == '\\')
+             if (c_isspace (*p) || *p == '\\')
                {
                  memmove (p + 1, p, nread - (p - cmdline));
                  nread++;
@@ -2944,14 +2747,9 @@ system_process_attributes (Lisp_Object pid)
        }
       if (!cmdline_size)
        {
-         if (!cmd)
-           cmd = "???";
-         if (!cmdsize)
-           cmdsize = strlen (cmd);
          cmdline_size = cmdsize + 2;
          cmdline = xmalloc (cmdline_size + 1);
-         strcpy (cmdline, "[");
-         strcat (strncat (cmdline, cmd, cmdsize), "]");
+         sprintf (cmdline, "[%.*s]", cmdsize, cmd);
        }
       emacs_close (fd);
       /* Command line is encoded in locale-coding-system; decode it.  */
@@ -3103,9 +2901,7 @@ system_process_attributes (Lisp_Object pid)
 static EMACS_TIME
 timeval_to_EMACS_TIME (struct timeval t)
 {
-  EMACS_TIME e;
-  EMACS_SET_SECS_NSECS (e, t.tv_sec, t.tv_usec * 1000);
-  return e;
+  return make_emacs_time (t.tv_sec, t.tv_usec * 1000);
 }
 
 static Lisp_Object
@@ -3213,9 +3009,8 @@ system_process_attributes (Lisp_Object pid)
                 attrs);
   attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.ki_rusage.ru_stime)),
                 attrs);
-  EMACS_ADD_TIME (t,
-                 timeval_to_EMACS_TIME (proc.ki_rusage.ru_utime),
-                 timeval_to_EMACS_TIME (proc.ki_rusage.ru_stime));
+  t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage.ru_utime),
+                     timeval_to_EMACS_TIME (proc.ki_rusage.ru_stime));
   attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
 
   attrs = Fcons (Fcons (Qcutime,
@@ -3224,9 +3019,8 @@ system_process_attributes (Lisp_Object pid)
   attrs = Fcons (Fcons (Qcstime,
                        make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
                 attrs);
-  EMACS_ADD_TIME (t,
-                 timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_utime),
-                 timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_stime));
+  t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_utime),
+                     timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_stime));
   attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs);
 
   attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (proc.ki_numthreads)),
@@ -3238,8 +3032,8 @@ system_process_attributes (Lisp_Object pid)
   attrs = Fcons (Fcons (Qrss,   make_number (proc.ki_rssize * pagesize >> 10)),
                 attrs);
 
-  EMACS_GET_TIME (now);
-  EMACS_SUB_TIME (t, now, timeval_to_EMACS_TIME (proc.ki_start));
+  now = current_emacs_time ();
+  t = sub_emacs_time (now, timeval_to_EMACS_TIME (proc.ki_start));
   attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
 
   len = sizeof fscale;
@@ -3278,7 +3072,7 @@ system_process_attributes (Lisp_Object pid)
 
       decoded_comm =
        (code_convert_string_norecord
-        (make_unibyte_string (args, strlen (args)),
+        (build_unibyte_string (args),
          Vlocale_coding_system, 0));
 
       attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);