Simplify by avoiding confusing use of strncpy etc.
[bpt/emacs.git] / src / sysdep.c
index 4719a69..ed92676 100644 (file)
@@ -1,6 +1,5 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+   Copyright (C) 1985-1988, 1993-1995, 1999-2012
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -18,10 +17,7 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
-
 #include <ctype.h>
 #include <signal.h>
 #include <stdio.h>
@@ -30,97 +26,59 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <pwd.h>
 #include <grp.h>
 #endif /* HAVE_PWD_H */
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif /* HAVE_LIMITS_H */
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif /* HAVE_ALLOCA_H */
 
-#include "lisp.h"
-/* Including stdlib.h isn't necessarily enough to get srandom
-   declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2.  */
+#include <allocator.h>
+#include <careadlinkat.h>
+#include <ignore-value.h>
+#include <utimens.h>
 
-/* The w32 build defines select stuff in w32.h, which is included by
-   sys/select.h (included below).   */
-#ifndef WINDOWSNT
+#include "lisp.h"
 #include "sysselect.h"
+#include "blockinput.h"
+
+#ifdef BSD_SYSTEM
+#include <sys/param.h>
+#include <sys/sysctl.h>
 #endif
 
-#include "blockinput.h"
+#ifdef __FreeBSD__
+#include <sys/user.h>
+#include <sys/resource.h>
+#include <math.h>
+#endif
 
 #ifdef WINDOWSNT
 #define read sys_read
 #define write sys_write
 #include <windows.h>
-#ifndef NULL
-#define NULL 0
-#endif
 #endif /* not WINDOWSNT */
 
-/* Does anyone other than VMS need this? */
-#ifndef fwrite
-#define sys_fwrite fwrite
-#else
-#undef fwrite
-#endif
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
 
-#ifdef HAVE_SETPGID
-#if !defined (USG) || defined (BSD_PGRPS)
-#undef setpgrp
-#define setpgrp setpgid
-#endif
-#endif
-
 /* Get SI_SRPC_DOMAIN, if it is available.  */
 #ifdef HAVE_SYS_SYSTEMINFO_H
 #include <sys/systeminfo.h>
 #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>
-
-#if __DJGPP__ > 1
-extern int etext;
-extern unsigned start __asm__ ("start");
-#endif
-#endif
-
-#ifndef USE_CRT_DLL
-#ifndef errno
-extern int errno;
-#endif
 #endif
 
 #include <sys/file.h>
-
-#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
-#endif
-
-#ifndef MSDOS
-#include <sys/ioctl.h>
-#endif
 
 #include "systty.h"
 #include "syswait.h"
 
-#if defined (USG)
+#ifdef HAVE_SYS_UTSNAME_H
 #include <sys/utsname.h>
 #include <memory.h>
-#endif /* USG */
-
-extern int quit_char;
+#endif /* HAVE_SYS_UTSNAME_H */
 
 #include "keyboard.h"
 #include "frame.h"
@@ -132,11 +90,6 @@ extern int quit_char;
 #include "process.h"
 #include "cm.h"  /* for reset_sys_modes */
 
-/* For serial_configure and serial_open.  */
-extern Lisp_Object QCport, QCspeed, QCprocess;
-extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
-extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
-
 #ifdef WINDOWSNT
 #include <direct.h>
 /* In process.h which conflicts with the local copy.  */
@@ -148,51 +101,27 @@ extern char *getwd (char *);
 
 #include "syssignal.h"
 #include "systime.h"
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
 
-#ifndef HAVE_UTIMES
-#ifndef HAVE_STRUCT_UTIMBUF
-/* We want to use utime rather than utimes, but we couldn't find the
-   structure declaration.  We'll use the traditional one.  */
-struct utimbuf {
-  long actime;
-  long modtime;
-};
-#endif
+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 *);
 #endif
 
-/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
-#ifndef LPASS8
-#define LPASS8 0
+/* 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.  */
+extern void tputs (const char *, int, int (*)(int));
+
 static const int baud_convert[] =
   {
     0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
     1800, 2400, 4800, 9600, 19200, 38400
   };
 
-#ifdef HAVE_SPEED_T
-#include <termios.h>
-#else
-#if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
-#else
-#if defined (HAVE_TERMIOS_H) && defined (GNU_LINUX)
-#include <termios.h>
-#endif
-#endif
-#endif
-
-int emacs_ospeed;
-
-void croak P_ ((char *)) NO_RETURN;
-
-/* Temporary used by `sigblock' when defined in terms of signprocmask.  */
-
-SIGMASKTYPE sigprocmask_set;
-
 
 #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
 
@@ -200,7 +129,7 @@ SIGMASKTYPE sigprocmask_set;
    Any other returned value must be freed with free. This is used
    only when get_current_dir_name is not defined on the system.  */
 char*
-get_current_dir_name ()
+get_current_dir_name (void)
 {
   char *buf;
   char *pwd;
@@ -219,7 +148,7 @@ get_current_dir_name ()
 #endif
       )
     {
-      buf = (char *) malloc (strlen (pwd) + 1);
+      buf = malloc (strlen (pwd) + 1);
       if (!buf)
         return NULL;
       strcpy (buf, pwd);
@@ -228,7 +157,7 @@ get_current_dir_name ()
   else
     {
       size_t buf_size = 1024;
-      buf = (char *) malloc (buf_size);
+      buf = malloc (buf_size);
       if (!buf)
         return NULL;
       for (;;)
@@ -243,7 +172,7 @@ get_current_dir_name ()
               return NULL;
             }
           buf_size *= 2;
-          buf = (char *) realloc (buf, buf_size);
+          buf = realloc (buf, buf_size);
           if (!buf)
             return NULL;
         }
@@ -252,7 +181,7 @@ get_current_dir_name ()
   else
     {
       /* We need MAXPATHLEN here.  */
-      buf = (char *) malloc (MAXPATHLEN + 1);
+      buf = malloc (MAXPATHLEN + 1);
       if (!buf)
         return NULL;
       if (getwd (buf) == NULL)
@@ -272,7 +201,7 @@ get_current_dir_name ()
 /* Discard pending input on all input descriptors.  */
 
 void
-discard_tty_input ()
+discard_tty_input (void)
 {
 #ifndef WINDOWSNT
   struct emacs_tty buf;
@@ -290,8 +219,8 @@ discard_tty_input ()
       {
         if (tty->input)         /* Is the device suspended? */
           {
-            EMACS_GET_TTY (fileno (tty->input), &buf);
-            EMACS_SET_TTY (fileno (tty->input), &buf, 0);
+            emacs_get_tty (fileno (tty->input), &buf);
+            emacs_set_tty (fileno (tty->input), &buf, 0);
           }
       }
   }
@@ -326,6 +255,8 @@ stuff_char (char c)
 void
 init_baud_rate (int fd)
 {
+  int emacs_ospeed;
+
   if (noninteractive)
     emacs_ospeed = 0;
   else
@@ -333,32 +264,11 @@ init_baud_rate (int fd)
 #ifdef DOS_NT
     emacs_ospeed = 15;
 #else  /* not DOS_NT */
-#ifdef HAVE_TERMIOS
       struct termios sg;
 
       sg.c_cflag = B9600;
       tcgetattr (fd, &sg);
       emacs_ospeed = cfgetospeed (&sg);
-#else /* not TERMIOS */
-#ifdef HAVE_TERMIO
-      struct termio sg;
-
-      sg.c_cflag = B9600;
-#ifdef HAVE_TCATTR
-      tcgetattr (fd, &sg);
-#else
-      ioctl (fd, TCGETA, &sg);
-#endif
-      emacs_ospeed = sg.c_cflag & CBAUD;
-#else /* neither TERMIOS nor TERMIO */
-      struct sgttyb sg;
-
-      sg.sg_ospeed = B9600;
-      if (ioctl (fd, TIOCGETP, &sg) < 0)
-       abort ();
-      emacs_ospeed = sg.sg_ospeed;
-#endif /* not HAVE_TERMIO */
-#endif /* not HAVE_TERMIOS */
 #endif /* not DOS_NT */
     }
 
@@ -369,49 +279,19 @@ init_baud_rate (int fd)
 }
 
 \f
-/*ARGSUSED*/
-void
-set_exclusive_use (fd)
-     int fd;
-{
-#ifdef FIOCLEX
-  ioctl (fd, FIOCLEX, 0);
-#endif
-  /* Ok to do nothing if this feature does not exist */
-}
-\f
-#ifndef subprocesses
-
-wait_without_blocking ()
-{
-#ifdef BSD_SYSTEM
-  wait3 (0, WNOHANG | WUNTRACED, 0);
-#else
-  croak ("wait_without_blocking");
-#endif
-  synch_process_alive = 0;
-}
-
-#endif /* not subprocesses */
 
-int wait_debugging;   /* Set nonzero to make following function work under dbx
-                        (at least for bsd).  */
+/* Set nonzero to make following function work under dbx
+   (at least for bsd).  */
+int wait_debugging EXTERNALLY_VISIBLE;
 
-SIGTYPE
-wait_for_termination_signal ()
-{}
-
-/* Wait for subprocess with process id `pid' to terminate and
-   make sure it will get eliminated (not remain forever as a zombie) */
+#ifndef MSDOS
 
-void
-wait_for_termination (pid)
-     int pid;
+static void
+wait_for_termination_1 (pid_t pid, int interruptible)
 {
   while (1)
     {
-#ifdef subprocesses
-#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined(__GNU__)
+#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. */
@@ -431,7 +311,10 @@ wait_for_termination (pid)
       else
        sigpause (SIGEMPTYMASK);
 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#ifdef POSIX_SIGNALS    /* would this work for GNU/Linux as well? */
+#ifdef WINDOWSNT
+      wait (0);
+      break;
+#else /* not WINDOWSNT */
       sigblock (sigmask (SIGCHLD));
       errno = 0;
       if (kill (pid, 0) == -1 && errno == ESRCH)
@@ -441,43 +324,28 @@ wait_for_termination (pid)
        }
 
       sigsuspend (&empty_mask);
-#else /* not POSIX_SIGNALS */
-#ifdef HAVE_SYSV_SIGPAUSE
-      sighold (SIGCHLD);
-      if (0 > kill (pid, 0))
-       {
-         sigrelse (SIGCHLD);
-         break;
-       }
-      sigpause (SIGCHLD);
-#else /* not HAVE_SYSV_SIGPAUSE */
-#ifdef WINDOWSNT
-      wait (0);
-      break;
-#else /* not WINDOWSNT */
-      if (0 > kill (pid, 0))
-       break;
-      /* Using sleep instead of pause avoids timing error.
-        If the inferior dies just before the sleep,
-        we lose just one second.  */
-      sleep (1);
 #endif /* not WINDOWSNT */
-#endif /* not HAVE_SYSV_SIGPAUSE */
-#endif /* not POSIX_SIGNALS */
 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#else /* not subprocesses */
-#if __DJGPP__ > 1
-      break;
-#else /* not __DJGPP__ > 1 */
-      if (kill (pid, 0) < 0)
-       break;
-      wait (0);
-#endif /* not __DJGPP__ > 1*/
-#endif /* not subprocesses */
+      if (interruptible)
+       QUIT;
     }
 }
 
-#ifdef subprocesses
+/* Wait for subprocess with process id `pid' to terminate and
+   make sure it will get eliminated (not remain forever as a zombie) */
+
+void
+wait_for_termination (pid_t pid)
+{
+  wait_for_termination_1 (pid, 0);
+}
+
+/* Like the above, but allow keyboard interruption. */
+void
+interruptible_wait_for_termination (pid_t pid)
+{
+  wait_for_termination_1 (pid, 1);
+}
 
 /*
  *     flush any pending output
@@ -485,25 +353,9 @@ wait_for_termination (pid)
  */
 
 void
-flush_pending_output (channel)
-     int channel;
+flush_pending_output (int channel)
 {
-#ifdef HAVE_TERMIOS
-  /* If we try this, we get hit with SIGTTIN, because
-     the child's tty belongs to the child's pgrp. */
-#else
-#ifdef TCFLSH
-  ioctl (channel, TCFLSH, 1);
-#else
-#ifdef TIOCFLUSH
-  int zero = 0;
-  /* 3rd arg should be ignored
-     but some 4.2 kernels actually want the address of an int
-     and nonzero means something different.  */
-  ioctl (channel, TIOCFLUSH, &zero);
-#endif
-#endif
-#endif
+  /* FIXME: maybe this function should be removed */
 }
 \f
 /*  Set up the terminal at the other end of a pseudo-terminal that
@@ -512,15 +364,12 @@ flush_pending_output (channel)
     in Emacs.  No padding needed for insertion into an Emacs buffer.  */
 
 void
-child_setup_tty (out)
-     int out;
+child_setup_tty (int out)
 {
-#ifndef DOS_NT
+#ifndef WINDOWSNT
   struct emacs_tty s;
 
-  EMACS_GET_TTY (out, &s);
-
-#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
+  emacs_get_tty (out, &s);
   s.main.c_oflag |= OPOST;     /* Enable output postprocessing */
   s.main.c_oflag &= ~ONLCR;    /* Disable map of NL to CR-NL on output */
 #ifdef NLDLY
@@ -547,8 +396,6 @@ child_setup_tty (out)
 #endif
   s.main.c_oflag &= ~TAB3;     /* Disable tab expansion */
   s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
-  s.main.c_lflag |= ICANON;    /* Enable erase/kill and eof processing */
-  s.main.c_cc[VEOF] = 04;      /* insure that EOF is Control-D */
   s.main.c_cc[VERASE] = CDISABLE;      /* disable erase processing */
   s.main.c_cc[VKILL] = CDISABLE;       /* disable kill processing */
 
@@ -566,11 +413,6 @@ child_setup_tty (out)
 #endif /* not SIGNALS_VIA_CHARACTERS */
 
 #ifdef AIX
-/* AIX enhanced edit loses NULs, so disable it */
-#ifndef IBMR2AIX
-  s.main.c_line = 0;
-  s.main.c_iflag &= ~ASCEDIT;
-#endif
   /* Also, PTY overloads NUL and BREAK.
      don't ignore break, but don't signal either, so it looks like NUL.  */
   s.main.c_iflag &= ~IGNBRK;
@@ -578,42 +420,53 @@ child_setup_tty (out)
   /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
      unconditionally.  Then a SIGNALS_VIA_CHARACTERS conditional
      would force it to 0377.  That looks like duplicated code.  */
-  s.main.c_cc[VEOL] = CDISABLE;
   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 #endif /* AIX */
 
-#else /* not HAVE_TERMIO */
-
-  s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
-                      | CBREAK | TANDEM);
-  s.main.sg_flags |= LPASS8;
-  s.main.sg_erase = 0377;
-  s.main.sg_kill = 0377;
-  s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */
-
-#endif /* not HAVE_TERMIO */
-
-  EMACS_SET_TTY (out, &s, 0);
-
-#endif /* not DOS_NT */
+  /* We originally enabled ICANON (and set VEOF to 04), and then had
+     process.c send additional EOF chars to flush the output when faced
+     with long lines, but this leads to weird effects when the
+     subprocess has disabled ICANON and ends up seeing those spurious
+     extra EOFs.  So we don't send EOFs any more in
+     process.c:send_process.  First we tried to disable ICANON by
+     default, so if a subsprocess sets up ICANON, it's his problem (or
+     the Elisp package that talks to it) to deal with lines that are
+     too long.  But this disables some features, such as the ability
+     to send EOF signals.  So we re-enabled ICANON but there is no
+     more "send eof to flush" going on (which is wrong and unportable
+     in itself).  The correct way to handle too much output is to
+     buffer what could not be written and then write it again when
+     select returns ok for writing.  This has it own set of
+     problems.  Write is now asynchronous, is that a problem?  How much
+     do we buffer, and what do we do when that limit is reached?  */
+
+  s.main.c_lflag |= ICANON;    /* Enable line editing and eof processing */
+  s.main.c_cc[VEOF] = 'D'&037; /* Control-D */
+#if 0      /* These settings only apply to non-ICANON mode. */
+  s.main.c_cc[VMIN] = 1;
+  s.main.c_cc[VTIME] = 0;
+#endif
+
+  emacs_set_tty (out, &s, 0);
+#endif /* not WINDOWSNT */
 }
+#endif /* not MSDOS */
 
-#endif /* subprocesses */
 \f
 /* Record a signal code and the handler for it.  */
 struct save_signal
 {
   int code;
-  SIGTYPE (*handler) P_ ((int));
+  void (*handler) (int);
 };
 
-static void save_signal_handlers P_ ((struct save_signal *));
-static void restore_signal_handlers P_ ((struct save_signal *));
+static void save_signal_handlers (struct save_signal *);
+static void restore_signal_handlers (struct save_signal *);
 
 /* Suspend the Emacs process; give terminal to its superior.  */
 
 void
-sys_suspend ()
+sys_suspend (void)
 {
 #if defined (SIGTSTP) && !defined (MSDOS)
 
@@ -634,7 +487,7 @@ sys_suspend ()
 /* Fork a subshell.  */
 
 void
-sys_subshell ()
+sys_subshell (void)
 {
 #ifdef DOS_NT  /* Demacs 1.1.2 91/10/20 Manabu Higashida */
   int st;
@@ -643,7 +496,8 @@ sys_subshell ()
   int pid;
   struct save_signal saved_handlers[5];
   Lisp_Object dir;
-  unsigned char *str = 0;
+  unsigned char *volatile str_volatile = 0;
+  unsigned char *str;
   int len;
 
   saved_handlers[0].code = SIGINT;
@@ -667,19 +521,17 @@ sys_subshell ()
     goto xyzzy;
 
   dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
-  str = (unsigned char *) alloca (SCHARS (dir) + 2);
+  str_volatile = str = alloca (SCHARS (dir) + 2);
   len = SCHARS (dir);
-  bcopy (SDATA (dir), str, len);
+  memcpy (str, SDATA (dir), len);
   if (str[len - 1] != '/') str[len++] = '/';
   str[len] = 0;
  xyzzy:
 
 #ifdef DOS_NT
   pid = 0;
-#if __DJGPP__ > 1
   save_signal_handlers (saved_handlers);
   synch_process_alive = 1;
-#endif /* __DJGPP__ > 1 */
 #else
   pid = vfork ();
   if (pid == -1)
@@ -688,7 +540,7 @@ sys_subshell ()
 
   if (pid == 0)
     {
-      char *sh = 0;
+      const char *sh = 0;
 
 #ifdef DOS_NT    /* MW, Aug 1993 */
       getwd (oldwd);
@@ -701,21 +553,16 @@ sys_subshell ()
        sh = "sh";
 
       /* Use our buffer's default directory for the subshell.  */
-      if (str)
-       chdir ((char *) str);
-
-#ifdef subprocesses
-      close_process_descs ();  /* Close Emacs's pipes/ptys */
+      str = str_volatile;
+      if (str && chdir ((char *) str) != 0)
+       {
+#ifndef DOS_NT
+         ignore_value (write (1, "Can't chdir\n", 12));
+         _exit (1);
 #endif
+       }
 
-#ifdef SET_EMACS_PRIORITY
-      {
-       extern EMACS_INT emacs_priority;
-
-       if (emacs_priority < 0)
-         nice (-emacs_priority);
-      }
-#endif
+      close_process_descs ();  /* Close Emacs's pipes/ptys */
 
 #ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
       {
@@ -731,7 +578,7 @@ sys_subshell ()
            setenv ("PWD", str, 1);
          }
        st = system (sh);
-       chdir (oldwd);
+       chdir (oldwd);  /* FIXME: Do the right thing on chdir failure.  */
        if (epwd)
          putenv (old_pwd);     /* restore previous value */
       }
@@ -739,19 +586,19 @@ sys_subshell ()
 #ifdef  WINDOWSNT
       /* Waits for process completion */
       pid = _spawnlp (_P_WAIT, sh, sh, NULL);
-      chdir (oldwd);
+      chdir (oldwd);   /* FIXME: Do the right thing on chdir failure.  */
       if (pid == -1)
        write (1, "Can't execute subshell", 22);
 #else   /* not WINDOWSNT */
       execlp (sh, sh, (char *) 0);
-      write (1, "Can't execute subshell", 22);
+      ignore_value (write (1, "Can't execute subshell", 22));
       _exit (1);
 #endif  /* not WINDOWSNT */
 #endif /* not MSDOS */
     }
 
   /* Do this now if we did not do it before.  */
-#if !defined (MSDOS) || __DJGPP__ == 1
+#ifndef MSDOS
   save_signal_handlers (saved_handlers);
   synch_process_alive = 1;
 #endif
@@ -764,20 +611,18 @@ sys_subshell ()
 }
 
 static void
-save_signal_handlers (saved_handlers)
-     struct save_signal *saved_handlers;
+save_signal_handlers (struct save_signal *saved_handlers)
 {
   while (saved_handlers->code)
     {
       saved_handlers->handler
-       = (SIGTYPE (*) P_ ((int))) signal (saved_handlers->code, SIG_IGN);
+        = (void (*) (int)) signal (saved_handlers->code, SIG_IGN);
       saved_handlers++;
     }
 }
 
 static void
-restore_signal_handlers (saved_handlers)
-     struct save_signal *saved_handlers;
+restore_signal_handlers (struct save_signal *saved_handlers)
 {
   while (saved_handlers->code)
     {
@@ -793,7 +638,7 @@ init_sigio (int fd)
 {
 }
 
-void
+static void
 reset_sigio (int fd)
 {
 }
@@ -811,11 +656,10 @@ unrequest_sigio (void)
 #else
 #ifdef F_SETFL
 
-int old_fcntl_flags[MAXDESC];
+static int old_fcntl_flags[MAXDESC];
 
 void
-init_sigio (fd)
-     int fd;
+init_sigio (int fd)
 {
 #ifdef FASYNC
   old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
@@ -824,9 +668,8 @@ init_sigio (fd)
   interrupts_deferred = 0;
 }
 
-void
-reset_sigio (fd)
-     int fd;
+static void
+reset_sigio (int fd)
 {
 #ifdef FASYNC
   fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
@@ -838,7 +681,7 @@ reset_sigio (fd)
 /* XXX Yeah, but you need it for SIGIO, don't you? */
 
 void
-request_sigio ()
+request_sigio (void)
 {
   if (noninteractive)
     return;
@@ -853,7 +696,7 @@ request_sigio ()
 
 void
 unrequest_sigio (void)
-{ 
+{
   if (noninteractive)
     return;
 
@@ -873,7 +716,7 @@ unrequest_sigio (void)
 #ifndef MSDOS
 
 void
-request_sigio ()
+request_sigio (void)
 {
   if (noninteractive || read_socket_hook)
     return;
@@ -882,7 +725,7 @@ request_sigio ()
 }
 
 void
-unrequest_sigio ()
+unrequest_sigio (void)
 {
   if (noninteractive || read_socket_hook)
     return;
@@ -894,65 +737,7 @@ unrequest_sigio ()
 #endif /* FASYNC */
 #endif /* F_SETFL */
 #endif /* SIGIO */
-\f
-/* Saving and restoring the process group of Emacs's terminal.  */
-
-#ifdef BSD_PGRPS
-
-/* The process group of which Emacs was a member when it initially
-   started.
-
-   If Emacs was in its own process group (i.e. inherited_pgroup ==
-   getpid ()), then we know we're running under a shell with job
-   control (Emacs would never be run as part of a pipeline).
-   Everything is fine.
-
-   If Emacs was not in its own process group, then we know we're
-   running under a shell (or a caller) that doesn't know how to
-   separate itself from Emacs (like sh).  Emacs must be in its own
-   process group in order to receive SIGIO correctly.  In this
-   situation, we put ourselves in our own pgroup, forcibly set the
-   tty's pgroup to our pgroup, and make sure to restore and reinstate
-   the tty's pgroup just like any other terminal setting.  If
-   inherited_group was not the tty's pgroup, then we'll get a
-   SIGTTmumble when we try to change the tty's pgroup, and a CONT if
-   it goes foreground in the future, which is what should happen.
-
-   This variable is initialized in emacs.c.  */
-int inherited_pgroup;
-
-/* Split off the foreground process group to Emacs alone.  When we are
-   in the foreground, but not started in our own process group,
-   redirect the tty device handle FD to point to our own process
-   group.  We need to be in our own process group to receive SIGIO
-   properly.  */
-static void
-narrow_foreground_group (int fd)
-{
-  int me = getpid ();
-
-  setpgrp (0, inherited_pgroup);
-#if 0
-  /* XXX inherited_pgroup should not be zero here, but GTK seems to
-     mess this up. */
-  if (! inherited_pgroup)
-    abort ();                   /* Should not happen. */
-#endif
-  if (inherited_pgroup != me)
-      EMACS_SET_TTY_PGRP (fd, &me); /* XXX This only works on the controlling tty. */
-  setpgrp (0, me);
-}
 
-/* Set the tty to our original foreground group.  */
-static void
-widen_foreground_group (int fd)
-{
-  if (inherited_pgroup != getpid ())
-    EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
-  setpgrp (0, inherited_pgroup);
-}
-
-#endif /* BSD_PGRPS */
 \f
 /* Getting and setting emacs_tty structures.  */
 
@@ -960,43 +745,14 @@ widen_foreground_group (int fd)
    Return zero if all's well, or -1 if we ran into an error we
    couldn't deal with.  */
 int
-emacs_get_tty (fd, settings)
-     int fd;
-     struct emacs_tty *settings;
+emacs_get_tty (int fd, struct emacs_tty *settings)
 {
   /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
-#ifdef HAVE_TCATTR
+#ifndef DOS_NT
   /* We have those nifty POSIX tcmumbleattr functions.  */
-  bzero (&settings->main, sizeof (settings->main));
+  memset (&settings->main, 0, sizeof (settings->main));
   if (tcgetattr (fd, &settings->main) < 0)
     return -1;
-
-#else
-#ifdef HAVE_TERMIO
-  /* The SYSV-style interface?  */
-  if (ioctl (fd, TCGETA, &settings->main) < 0)
-    return -1;
-
-#else
-#ifndef DOS_NT
-  /* I give up - I hope you have the BSD ioctls.  */
-  if (ioctl (fd, TIOCGETP, &settings->main) < 0)
-    return -1;
-#endif /* not DOS_NT */
-#endif
-#endif
-
-  /* Suivant - Do we have to get struct ltchars data?  */
-#ifdef HAVE_LTCHARS
-  if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
-    return -1;
-#endif
-
-  /* How about a struct tchars and a wordful of lmode bits?  */
-#ifdef HAVE_TCHARS
-  if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
-      || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
-    return -1;
 #endif
 
   /* We have survived the tempest.  */
@@ -1009,13 +765,10 @@ emacs_get_tty (fd, settings)
    Return 0 if all went well, and -1 if anything failed.  */
 
 int
-emacs_set_tty (fd, settings, flushp)
-     int fd;
-     struct emacs_tty *settings;
-     int flushp;
+emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
 {
   /* Set the primary parameters - baud rate, character size, etcetera.  */
-#ifdef HAVE_TCATTR
+#ifndef DOS_NT
   int i;
   /* We have those nifty POSIX tcmumbleattr functions.
      William J. Smith <wjs@wiis.wang.com> writes:
@@ -1037,7 +790,7 @@ emacs_set_tty (fd, settings, flushp)
       {
        struct termios new;
 
-       bzero (&new, sizeof (new));
+       memset (&new, 0, sizeof (new));
        /* Get the current settings, and see if they're what we asked for.  */
        tcgetattr (fd, &new);
        /* We cannot use memcmp on the whole structure here because under
@@ -1053,34 +806,6 @@ emacs_set_tty (fd, settings, flushp)
        else
          continue;
       }
-
-#else
-#ifdef HAVE_TERMIO
-  /* The SYSV-style interface?  */
-  if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
-    return -1;
-
-#else
-#ifndef DOS_NT
-  /* I give up - I hope you have the BSD ioctls.  */
-  if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
-    return -1;
-#endif /* not DOS_NT */
-
-#endif
-#endif
-
-  /* Suivant - Do we have to get struct ltchars data?  */
-#ifdef HAVE_LTCHARS
-  if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
-    return -1;
-#endif
-
-  /* How about a struct tchars and a wordful of lmode bits?  */
-#ifdef HAVE_TCHARS
-  if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
-      || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
-    return -1;
 #endif
 
   /* We have survived the tempest.  */
@@ -1090,7 +815,7 @@ emacs_set_tty (fd, settings, flushp)
 \f
 
 #ifdef F_SETOWN
-int old_fcntl_owner[MAXDESC];
+static int old_fcntl_owner[MAXDESC];
 #endif /* F_SETOWN */
 
 /* This may also be defined in stdio,
@@ -1103,13 +828,6 @@ unsigned char _sobuf[BUFSIZ+8];
 char _sobuf[BUFSIZ];
 #endif
 
-#ifdef HAVE_LTCHARS
-static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
-#endif
-#ifdef HAVE_TCHARS
-static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
-#endif
-
 /* Initialize the terminal mode on all tty devices that are currently
    open. */
 
@@ -1124,10 +842,10 @@ init_all_sys_modes (void)
 /* Initialize the terminal mode on the given tty device. */
 
 void
-init_sys_modes (tty_out)
-     struct tty_display_info *tty_out;
+init_sys_modes (struct tty_display_info *tty_out)
 {
   struct emacs_tty tty;
+  Lisp_Object terminal;
 
   Vtty_erase_char = Qnil;
 
@@ -1136,24 +854,15 @@ init_sys_modes (tty_out)
 
   if (!tty_out->output)
     return;                     /* The tty is suspended. */
-  
-#ifdef BSD_PGRPS
-#if 0
-  /* read_socket_hook is not global anymore.  I think doing this
-     unconditionally will not cause any problems. */
-  if (! read_socket_hook && EQ (Vinitial_window_system, Qnil))
-#endif
-    narrow_foreground_group (fileno (tty_out->input));
-#endif
 
   if (! tty_out->old_tty)
-    tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
-      
-  EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty);
+    tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty);
+
+  emacs_get_tty (fileno (tty_out->input), tty_out->old_tty);
 
   tty = *tty_out->old_tty;
 
-#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
+#if !defined (DOS_NT)
   XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
 
   tty.main.c_iflag |= (IGNBRK);        /* Ignore break condition */
@@ -1190,7 +899,9 @@ init_sys_modes (tty_out)
       tty.main.c_cflag &= ~PARENB;/* Don't check parity */
     }
 #endif
-  if (tty_out->input == stdin)
+
+  XSETTERMINAL(terminal, tty_out->terminal);
+  if (!NILP (Fcontrolling_tty_p (terminal)))
     {
       tty.main.c_cc[VINTR] = quit_char;        /* C-g (usually) gives SIGINT */
       /* Set up C-g for both SIGQUIT and SIGINT.
@@ -1206,7 +917,7 @@ init_sys_modes (tty_out)
          means that the interrupt and quit feature must be
          disabled on secondary ttys, or we would not even see the
          keypress.
-         
+
          Note that even though emacsclient could have special code
          to pass SIGINT to Emacs, we should _not_ enable
          interrupt/quit keys for emacsclient frames.  This means
@@ -1224,13 +935,12 @@ init_sys_modes (tty_out)
   tty.main.c_cc[VSWTCH] = CDISABLE;    /* Turn off shell layering use
                                           of C-z */
 #endif /* VSWTCH */
-  
-#if defined (__mips__) || defined (HAVE_TCATTR)
+
 #ifdef VSUSP
-  tty.main.c_cc[VSUSP] = CDISABLE;     /* Turn off mips handling of C-z.  */
+  tty.main.c_cc[VSUSP] = CDISABLE;     /* Turn off handling of C-z.  */
 #endif /* VSUSP */
 #ifdef V_DSUSP
-  tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y.  */
+  tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off handling of C-y.  */
 #endif /* V_DSUSP */
 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
   tty.main.c_cc[VDSUSP] = CDISABLE;
@@ -1266,19 +976,12 @@ init_sys_modes (tty_out)
       tty.main.c_cc[VSTOP] = CDISABLE;
 #endif /* VSTOP */
     }
-#endif /* mips or HAVE_TCATTR */
 
 #ifdef AIX
-#ifndef IBMR2AIX
-  /* AIX enhanced edit loses NULs, so disable it.  */
-  tty.main.c_line = 0;
-  tty.main.c_iflag &= ~ASCEDIT;
-#else
   tty.main.c_cc[VSTRT] = CDISABLE;
   tty.main.c_cc[VSTOP] = CDISABLE;
   tty.main.c_cc[VSUSP] = CDISABLE;
   tty.main.c_cc[VDSUSP] = CDISABLE;
-#endif /* IBMR2AIX */
   if (tty_out->flow_control)
     {
 #ifdef VSTART
@@ -1295,48 +998,15 @@ init_sys_modes (tty_out)
   tty.main.c_iflag &= ~IGNBRK;
   tty.main.c_iflag &= ~BRKINT;
 #endif
-#else /* if not HAVE_TERMIO */
-#ifndef DOS_NT
-  XSETINT (Vtty_erase_char, tty.main.sg_erase);
-  tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
-  if (meta_key)
-    tty.main.sg_flags |= ANYP;
-  tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
 #endif /* not DOS_NT */
-#endif /* not HAVE_TERMIO */
-
-  /* If going to use CBREAK mode, we must request C-g to interrupt
-     and turn off start and stop chars, etc.  If not going to use
-     CBREAK mode, do this anyway so as to turn off local flow
-     control for user coming over network on 4.2; in this case,
-     only t_stopc and t_startc really matter.  */
-#ifndef HAVE_TERMIO
-#ifdef HAVE_TCHARS
-  /* Note: if not using CBREAK mode, it makes no difference how we
-     set this */
-  tty.tchars = new_tchars;
-  tty.tchars.t_intrc = quit_char;
-  if (tty_out->flow_control)
-    {
-      tty.tchars.t_startc = '\021';
-      tty.tchars.t_stopc = '\023';
-    }
-  
-  tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode;
-  
-#endif /* HAVE_TCHARS */
-#endif /* not HAVE_TERMIO */
-
-#ifdef HAVE_LTCHARS
-  tty.ltchars = new_ltchars;
-#endif /* HAVE_LTCHARS */
+
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
   if (!tty_out->term_initted)
     internal_terminal_init ();
   dos_ttraw (tty_out);
 #endif
 
-  EMACS_SET_TTY (fileno (tty_out->input), &tty, 0);
+  emacs_set_tty (fileno (tty_out->input), &tty, 0);
 
   /* This code added to insure that, if flow-control is not to be used,
      we have an unlocked terminal at the start. */
@@ -1348,7 +1018,7 @@ init_sys_modes (tty_out)
   if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
 #endif
 
-#if defined (HAVE_TERMIOS) || defined (HPUX)
+#if !defined (DOS_NT)
 #ifdef TCOON
   if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
 #endif
@@ -1401,9 +1071,8 @@ init_sys_modes (tty_out)
 
   if (tty_out->term_initted && no_redraw_on_reenter)
     {
-      /* XXX This seems wrong on multi-tty. */
-      if (display_completed)
-       direct_output_forward_char (0);
+      /* We used to call "direct_output_forward_char(0)" here,
+        but it's not clear why, since it may not do anything anyway.  */
     }
   else
     {
@@ -1429,8 +1098,16 @@ tabs_safe_p (int fd)
 {
   struct emacs_tty etty;
 
-  EMACS_GET_TTY (fd, &etty);
-  return EMACS_TTY_TABS_OK (&etty);
+  emacs_get_tty (fd, &etty);
+#ifndef DOS_NT
+#ifdef TABDLY
+  return ((etty.main.c_oflag & TABDLY) != TAB3);
+#else /* not TABDLY */
+  return 1;
+#endif /* not TABDLY */
+#else /* DOS_NT */
+  return 0;
+#endif /* DOS_NT */
 }
 \f
 /* Get terminal size from system.
@@ -1440,8 +1117,7 @@ tabs_safe_p (int fd)
 void
 get_tty_size (int fd, int *widthp, int *heightp)
 {
-
-#ifdef TIOCGWINSZ
+#if defined TIOCGWINSZ
 
   /* BSD-style.  */
   struct winsize size;
@@ -1454,8 +1130,7 @@ get_tty_size (int fd, int *widthp, int *heightp)
       *heightp = size.ws_row;
     }
 
-#else
-#ifdef TIOCGSIZE
+#elif defined TIOCGSIZE
 
   /* SunOS - style.  */
   struct ttysize size;
@@ -1468,24 +1143,35 @@ get_tty_size (int fd, int *widthp, int *heightp)
       *heightp = size.ts_lines;
     }
 
-#else
-#ifdef MSDOS
+#elif defined WINDOWSNT
+
+  CONSOLE_SCREEN_BUFFER_INFO info;
+  if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info))
+    {
+      *widthp = info.srWindow.Right - info.srWindow.Left + 1;
+      *heightp = info.srWindow.Bottom - info.srWindow.Top + 1;
+    }
+  else
+    *widthp = *heightp = 0;
+
+#elif defined MSDOS
+
   *widthp = ScreenCols ();
   *heightp = ScreenRows ();
+
 #else /* system doesn't know size */
+
   *widthp = 0;
   *heightp = 0;
+
 #endif
-#endif /* not SunOS-style */
-#endif /* not BSD-style */
 }
 
 /* Set the logical window size associated with descriptor FD
    to HEIGHT and WIDTH.  This is used mainly with ptys.  */
 
 int
-set_window_size (fd, height, width)
-     int fd, height, width;
+set_window_size (int fd, int height, int width)
 {
 #ifdef TIOCSWINSZ
 
@@ -1533,8 +1219,7 @@ reset_all_sys_modes (void)
    bottom of the frame, turn off interrupt-driven I/O, etc.  */
 
 void
-reset_sys_modes (tty_out)
-     struct tty_display_info *tty_out;
+reset_sys_modes (struct tty_display_info *tty_out)
 {
   if (noninteractive)
     {
@@ -1546,11 +1231,11 @@ reset_sys_modes (tty_out)
 
   if (!tty_out->output)
     return;                     /* The tty is suspended. */
-  
+
   /* Go to and clear the last line of the terminal. */
 
   cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
-  
+
   /* Code adapted from tty_clear_end_of_line. */
   if (tty_out->TS_clr_line)
     {
@@ -1560,16 +1245,16 @@ reset_sys_modes (tty_out)
     {                  /* have to do it the hard way */
       int i;
       tty_turn_off_insert (tty_out);
-      
+
       for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
         {
           fputc (' ', tty_out->output);
         }
     }
-  
+
   cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
   fflush (tty_out->output);
-  
+
   if (tty_out->terminal->reset_terminal_modes_hook)
     tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
 
@@ -1594,7 +1279,7 @@ reset_sys_modes (tty_out)
 #endif /* F_SETFL */
 
   if (tty_out->old_tty)
-    while (EMACS_SET_TTY (fileno (tty_out->input),
+    while (emacs_set_tty (fileno (tty_out->input),
                           tty_out->old_tty, 0) < 0 && errno == EINTR)
       ;
 
@@ -1602,9 +1287,6 @@ reset_sys_modes (tty_out)
   dos_ttcooked ();
 #endif
 
-#ifdef BSD_PGRPS
-  widen_foreground_group (fileno (tty_out->input));
-#endif
 }
 \f
 #ifdef HAVE_PTYS
@@ -1612,8 +1294,7 @@ reset_sys_modes (tty_out)
 /* Set up the proper status flags for use of a pty.  */
 
 void
-setup_pty (fd)
-     int fd;
+setup_pty (int fd)
 {
   /* I'm told that TOICREMOTE does not mean control chars
      "can't be sent" but rather that they don't have
@@ -1639,7 +1320,7 @@ setup_pty (fd)
      Since the latter lossage is more benign, we may as well
      lose that way.  -- cph */
 #ifdef FIONBIO
-#if defined(UNIX98_PTYS)
+#if defined (UNIX98_PTYS)
   {
     int on = 1;
     ioctl (fd, FIONBIO, &on);
@@ -1649,88 +1330,6 @@ setup_pty (fd)
 }
 #endif /* HAVE_PTYS */
 \f
-#if !defined(CANNOT_DUMP) || !defined(SYSTEM_MALLOC)
-/* Some systems that cannot dump also cannot implement these.  */
-
-/*
- *     Return the address of the start of the text segment prior to
- *     doing an unexec.  After unexec the return value is undefined.
- *     See crt0.c for further explanation and _start.
- *
- */
-
-#if !(defined (__NetBSD__) && defined (__ELF__))
-#ifndef HAVE_TEXT_START
-char *
-start_of_text ()
-{
-#ifdef TEXT_START
-  return ((char *) TEXT_START);
-#else
-  extern int _start ();
-  return ((char *) _start);
-#endif /* TEXT_START */
-}
-#endif /* not HAVE_TEXT_START */
-#endif
-
-/*
- *     Return the address of the start of the data segment prior to
- *     doing an unexec.  After unexec the return value is undefined.
- *     See crt0.c for further information and definition of data_start.
- *
- *     Apparently, on BSD systems this is etext at startup.  On
- *     USG systems (swapping) this is highly mmu dependent and
- *     is also dependent on whether or not the program is running
- *     with shared text.  Generally there is a (possibly large)
- *     gap between end of text and start of data with shared text.
- *
- *     On Uniplus+ systems with shared text, data starts at a
- *     fixed address.  Each port (from a given oem) is generally
- *     different, and the specific value of the start of data can
- *     be obtained via the UniPlus+ specific "uvar" system call,
- *     however the method outlined in crt0.c seems to be more portable.
- *
- *     Probably what will have to happen when a USG unexec is available,
- *     at least on UniPlus, is temacs will have to be made unshared so
- *     that text and data are contiguous.  Then once loadup is complete,
- *     unexec will produce a shared executable where the data can be
- *     at the normal shared text boundary and the startofdata variable
- *     will be patched by unexec to the correct value.
- *
- */
-
-#ifndef start_of_data
-char *
-start_of_data ()
-{
-#ifdef DATA_START
-  return ((char *) DATA_START);
-#else
-#ifdef ORDINARY_LINK
-  /*
-   * This is a hack.  Since we're not linking crt0.c or pre_crt0.c,
-   * data_start isn't defined.  We take the address of environ, which
-   * is known to live at or near the start of the system crt0.c, and
-   * we don't sweat the handful of bytes that might lose.
-   */
-  extern char **environ;
-
-  return ((char *) &environ);
-#else
-  extern int data_start;
-  return ((char *) &data_start);
-#endif /* ORDINARY_LINK */
-#endif /* DATA_START */
-}
-#endif /* start_of_data */
-#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
-\f
-/* init_system_name sets up the string for the Lisp function
-   system-name to return. */
-
-extern Lisp_Object Vsystem_name;
-
 #ifdef HAVE_SOCKETS
 #include <sys/socket.h>
 #include <netdb.h>
@@ -1743,7 +1342,7 @@ extern int h_errno;
 #endif /* TRY_AGAIN */
 
 void
-init_system_name ()
+init_system_name (void)
 {
 #ifndef HAVE_GETHOSTNAME
   struct utsname uts;
@@ -1751,7 +1350,7 @@ init_system_name ()
   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
@@ -1767,7 +1366,7 @@ init_system_name ()
        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.
@@ -1776,7 +1375,7 @@ init_system_name ()
 #ifndef CANNOT_DUMP
   if (initialized)
 #endif /* not CANNOT_DUMP */
-    if (! index (hostname, '.'))
+    if (! strchr (hostname, '.'))
       {
        int count;
 #ifdef HAVE_GETADDRINFO
@@ -1784,7 +1383,7 @@ init_system_name ()
         struct addrinfo hints;
         int ret;
 
-        memset (&hints, 0, sizeof(hints));
+        memset (&hints, 0, sizeof (hints));
         hints.ai_socktype = SOCK_STREAM;
         hints.ai_flags = AI_CANONNAME;
 
@@ -1805,7 +1404,7 @@ init_system_name ()
             while (it)
               {
                 char *fqdn = it->ai_canonname;
-                if (fqdn && index (fqdn, '.')
+                if (fqdn && strchr (fqdn, '.')
                     && strcmp (fqdn, "localhost.localdomain") != 0)
                   break;
                 it = it->ai_next;
@@ -1830,292 +1429,50 @@ init_system_name ()
            if (! (hp == 0 && h_errno == TRY_AGAIN))
 #endif
 
-             break;
-
-           if (count >= 5)
-             break;
-           Fsleep_for (make_number (1), Qnil);
-         }
-
-       if (hp)
-         {
-           char *fqdn = (char *) hp->h_name;
-
-           if (!index (fqdn, '.'))
-             {
-               /* We still don't have a fully qualified domain name.
-                  Try to find one in the list of alternate names */
-               char **alias = hp->h_aliases;
-               while (*alias
-                      && (!index (*alias, '.')
-                          || !strcmp (*alias, "localhost.localdomain")))
-                 alias++;
-               if (*alias)
-                 fqdn = *alias;
-             }
-           hostname = fqdn;
-         }
-#endif /* !HAVE_GETADDRINFO */
-      }
-#endif /* HAVE_SOCKETS */
-  Vsystem_name = build_string (hostname);
-#endif /* HAVE_GETHOSTNAME */
-  {
-    unsigned char *p;
-    for (p = SDATA (Vsystem_name); *p; p++)
-      if (*p == ' ' || *p == '\t')
-       *p = '-';
-  }
-}
-\f
-#ifndef MSDOS
-#if !defined (HAVE_SELECT)
-
-#include "sysselect.h"
-#undef select
-
-#if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
-/* Cause explanatory error message at compile time,
-   since the select emulation is not good enough for X.  */
-int *x = &x_windows_lose_if_no_select_system_call;
-#endif
-
-/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
- * Only checks read descriptors.
- */
-/* How long to wait between checking fds in select */
-#define SELECT_PAUSE 1
-int select_alarmed;
-
-/* For longjmp'ing back to read_input_waiting.  */
-
-jmp_buf read_alarm_throw;
-
-/* Nonzero if the alarm signal should throw back to read_input_waiting.
-   The read_socket_hook function sets this to 1 while it is waiting.  */
-
-int read_alarm_should_throw;
-
-SIGTYPE
-select_alarm ()
-{
-  select_alarmed = 1;
-  signal (SIGALRM, SIG_IGN);
-  SIGNAL_THREAD_CHECK (SIGALRM);
-  if (read_alarm_should_throw)
-    longjmp (read_alarm_throw, 1);
-}
-
-#ifndef WINDOWSNT
-/* Only rfds are checked.  */
-int
-sys_select (nfds, rfds, wfds, efds, timeout)
-     int nfds;
-     SELECT_TYPE *rfds, *wfds, *efds;
-     EMACS_TIME *timeout;
-{
-  /* XXX This needs to be updated for multi-tty support.  Is there
-     anybody who needs to emulate select these days?  */ 
- int ravail = 0;
-  SELECT_TYPE orfds;
-  int timeoutval;
-  int *local_timeout;
-  extern int proc_buffered_char[];
-#ifndef subprocesses
-  int process_tick = 0, update_tick = 0;
-#else
-  extern int process_tick, update_tick;
-#endif
-  unsigned char buf;
-
-#if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
-  /* If we're using X, then the native select will work; we only need the
-     emulation for non-X usage.  */
-  if (!NILP (Vinitial_window_system))
-    return select (nfds, rfds, wfds, efds, timeout);
-#endif
-  timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
-  local_timeout = &timeoutval;
-  FD_ZERO (&orfds);
-  if (rfds)
-    {
-      orfds = *rfds;
-      FD_ZERO (rfds);
-    }
-  if (wfds)
-    FD_ZERO (wfds);
-  if (efds)
-    FD_ZERO (efds);
-
-  /* If we are looking only for the terminal, with no timeout,
-     just read it and wait -- that's more efficient.  */
-  if (*local_timeout == 100000 && process_tick == update_tick
-      && FD_ISSET (0, &orfds))
-    {
-      int fd;
-      for (fd = 1; fd < nfds; ++fd)
-       if (FD_ISSET (fd, &orfds))
-         goto hardway;
-      if (! detect_input_pending ())
-       read_input_waiting ();
-      FD_SET (0, rfds);
-      return 1;
-    }
-
- hardway:
-  /* Once a second, till the timer expires, check all the flagged read
-   * descriptors to see if any input is available.  If there is some then
-   * set the corresponding bit in the return copy of rfds.
-   */
-  while (1)
-    {
-      register int to_check, fd;
-
-      if (rfds)
-       {
-         for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
-           {
-             if (FD_ISSET (fd, &orfds))
-               {
-                 int avail = 0, status = 0;
-
-                 if (fd == 0)
-                   avail = detect_input_pending (); /* Special keyboard handler */
-                 else
-                   {
-#ifdef FIONREAD
-                     status = ioctl (fd, FIONREAD, &avail);
-#else /* no FIONREAD */
-                     /* Hoping it will return -1 if nothing available
-                        or 0 if all 0 chars requested are read.  */
-                     if (proc_buffered_char[fd] >= 0)
-                       avail = 1;
-                     else
-                       {
-                         avail = read (fd, &buf, 1);
-                         if (avail > 0)
-                           proc_buffered_char[fd] = buf;
-                       }
-#endif /* no FIONREAD */
-                   }
-                 if (status >= 0 && avail > 0)
-                   {
-                     FD_SET (fd, rfds);
-                     ravail++;
-                   }
-               }
-           }
-       }
-      if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
-       break;
-
-      turn_on_atimers (0);
-      signal (SIGALRM, select_alarm);
-      select_alarmed = 0;
-      alarm (SELECT_PAUSE);
-
-      /* Wait for a SIGALRM (or maybe a SIGTINT) */
-      while (select_alarmed == 0 && *local_timeout != 0
-            && process_tick == update_tick)
-       {
-         /* If we are interested in terminal input,
-            wait by reading the terminal.
-            That makes instant wakeup for terminal input at least.  */
-         if (FD_ISSET (0, &orfds))
-           {
-             read_input_waiting ();
-             if (detect_input_pending ())
-               select_alarmed = 1;
-           }
-         else
-           pause ();
-       }
-      (*local_timeout) -= SELECT_PAUSE;
-
-      /* Reset the old alarm if there was one.  */
-      turn_on_atimers (1);
-
-      if (*local_timeout == 0)  /* Stop on timer being cleared */
-       break;
-    }
-  return ravail;
-}
-#endif /* not WINDOWSNT */
-
-/* Read keyboard input into the standard buffer,
-   waiting for at least one character.  */
-
-void
-read_input_waiting ()
-{
-  /* XXX This needs to be updated for multi-tty support.  Is there
-     anybody who needs to emulate select these days?  */
-  int nread, i;
-  extern int quit_char;
-
-  if (read_socket_hook)
-    {
-      struct input_event hold_quit;
-
-      EVENT_INIT (hold_quit);
-      hold_quit.kind = NO_EVENT;
-
-      read_alarm_should_throw = 0;
-      if (! setjmp (read_alarm_throw))
-       nread = (*read_socket_hook) (0, 1, &hold_quit);
-      else
-       nread = -1;
-
-      if (hold_quit.kind != NO_EVENT)
-       kbd_buffer_store_event (&hold_quit);
-    }
-  else
-    {
-      struct input_event e;
-      char buf[3];
-      nread = read (fileno (stdin), buf, 1);
-      EVENT_INIT (e);
-
-      /* Scan the chars for C-g and store them in kbd_buffer.  */
-      e.kind = ASCII_KEYSTROKE_EVENT;
-      e.frame_or_window = selected_frame;
-      e.modifiers = 0;
-      for (i = 0; i < nread; i++)
-       {
-         /* Convert chars > 0177 to meta events if desired.
-            We do this under the same conditions that read_avail_input does.  */
-         if (read_socket_hook == 0)
-           {
-             /* If the user says she has a meta key, then believe her. */
-             if (meta_key == 1 && (buf[i] & 0x80))
-               e.modifiers = meta_modifier;
-             if (meta_key != 2)
-               buf[i] &= ~0x80;
-           }
+             break;
 
-         XSETINT (e.code, buf[i]);
-         kbd_buffer_store_event (&e);
-         /* Don't look at input that follows a C-g too closely.
-            This reduces lossage due to autorepeat on C-g.  */
-         if (buf[i] == quit_char)
-           break;
-       }
-    }
-}
+           if (count >= 5)
+             break;
+           Fsleep_for (make_number (1), Qnil);
+         }
 
-#if !defined (HAVE_SELECT)
-#define select sys_select
-#endif
+       if (hp)
+         {
+           char *fqdn = (char *) hp->h_name;
 
-#endif /* not HAVE_SELECT */
-#endif /* not MSDOS */
+           if (!strchr (fqdn, '.'))
+             {
+               /* We still don't have a fully qualified domain name.
+                  Try to find one in the list of alternate names */
+               char **alias = hp->h_aliases;
+               while (*alias
+                      && (!strchr (*alias, '.')
+                          || !strcmp (*alias, "localhost.localdomain")))
+                 alias++;
+               if (*alias)
+                 fqdn = *alias;
+             }
+           hostname = fqdn;
+         }
+#endif /* !HAVE_GETADDRINFO */
+      }
+#endif /* HAVE_SOCKETS */
+  Vsystem_name = build_string (hostname);
+#endif /* HAVE_GETHOSTNAME */
+  {
+    unsigned char *p;
+    for (p = SDATA (Vsystem_name); *p; p++)
+      if (*p == ' ' || *p == '\t')
+       *p = '-';
+  }
+}
 \f
 /* POSIX signals support - DJB */
 /* Anyone with POSIX signals should have ANSI C declarations */
 
-#ifdef POSIX_SIGNALS
+sigset_t empty_mask;
 
-sigset_t empty_mask, full_mask;
+#ifndef WINDOWSNT
 
 signal_handler_t
 sys_signal (int signal_number, signal_handler_t action)
@@ -2127,16 +1484,17 @@ sys_signal (int signal_number, signal_handler_t action)
 #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.  */
+     However, on some systems (only hpux11 at present) this resets the
+     timeout of `select' which means that `select' never finishes if
+     it keeps getting signals.
+     We define BROKEN_SA_RESTART 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
      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 defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
   if (noninteractive)
 # endif
     new_action.sa_flags = SA_RESTART;
@@ -2145,6 +1503,8 @@ sys_signal (int signal_number, signal_handler_t 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.  */
@@ -2167,7 +1527,7 @@ sigset_t
 sys_sigblock (sigset_t new_mask)
 {
   sigset_t old_mask;
-  sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
+  pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
   return (old_mask);
 }
 
@@ -2175,7 +1535,7 @@ sigset_t
 sys_sigunblock (sigset_t new_mask)
 {
   sigset_t old_mask;
-  sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
+  pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
   return (old_mask);
 }
 
@@ -2183,11 +1543,10 @@ sigset_t
 sys_sigsetmask (sigset_t new_mask)
 {
   sigset_t old_mask;
-  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
+  pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
   return (old_mask);
 }
 
-#endif /* POSIX_SIGNALS */
 \f
 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
 static char *my_sys_siglist[NSIG];
@@ -2198,12 +1557,9 @@ static char *my_sys_siglist[NSIG];
 #endif
 
 void
-init_signals ()
+init_signals (void)
 {
-#ifdef POSIX_SIGNALS
   sigemptyset (&empty_mask);
-  sigfillset (&full_mask);
-#endif
 
 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
   if (! initialized)
@@ -2299,7 +1655,7 @@ init_signals ()
       sys_siglist[SIGQUIT] = "Quit";
 # endif
 # ifdef SIGRETRACT
-      sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
+      sys_siglist[SIGRETRACT] = "Need to relinquish monitor mode";
 # endif
 # ifdef SIGSAK
       sys_siglist[SIGSAK] = "Secure attention";
@@ -2406,8 +1762,7 @@ init_signals ()
 #endif /* !RAND_BITS */
 
 void
-seed_random (arg)
-     long arg;
+seed_random (long int arg)
 {
 #ifdef HAVE_RANDOM
   srandom ((unsigned int)arg);
@@ -2421,33 +1776,26 @@ seed_random (arg)
 }
 
 /*
- * Build a full Emacs-sized word out of whatever we've got.
+ * Return a nonnegative random integer out of whatever we've got.
+ * It contains enough bits to make a random (signed) Emacs fixnum.
  * This suffices even for a 64-bit architecture with a 15-bit rand.
  */
-long
-get_random ()
-{
-  long val = random ();
-#if VALBITS > RAND_BITS
-  val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 2*RAND_BITS
-  val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 3*RAND_BITS
-  val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 4*RAND_BITS
-  val = (val << RAND_BITS) ^ random ();
-#endif /* need at least 5 */
-#endif /* need at least 4 */
-#endif /* need at least 3 */
-#endif /* need at least 2 */
-  return val & ((1L << VALBITS) - 1);
+EMACS_INT
+get_random (void)
+{
+  EMACS_UINT val = 0;
+  int i;
+  for (i = 0; i < (FIXNUM_BITS + RAND_BITS - 1) / RAND_BITS; i++)
+    val = (random () ^ (val << RAND_BITS)
+          ^ (val >> (BITS_PER_EMACS_INT - RAND_BITS)));
+  val ^= val >> (BITS_PER_EMACS_INT - FIXNUM_BITS);
+  return val & INTMASK;
 }
 
 #ifndef HAVE_STRERROR
 #ifndef WINDOWSNT
 char *
-strerror (errnum)
-     int errnum;
+strerror (int errnum)
 {
   extern char *sys_errlist[];
   extern int sys_nerr;
@@ -2458,11 +1806,52 @@ strerror (errnum)
 }
 #endif /* not WINDOWSNT */
 #endif /* ! HAVE_STRERROR */
+
+#ifndef HAVE_SNPRINTF
+/* Approximate snprintf as best we can on ancient hosts that lack it.  */
+int
+snprintf (char *buf, size_t bufsize, char const *format, ...)
+{
+  ptrdiff_t size = min (bufsize, PTRDIFF_MAX);
+  ptrdiff_t nbytes = size - 1;
+  va_list ap;
+
+  if (size)
+    {
+      va_start (ap, format);
+      nbytes = doprnt (buf, size, format, 0, ap);
+      va_end (ap);
+    }
+
+  if (nbytes == size - 1)
+    {
+      /* Calculate the length of the string that would have been created
+        had the buffer been large enough.  */
+      char stackbuf[4000];
+      char *b = stackbuf;
+      ptrdiff_t bsize = sizeof stackbuf;
+      va_start (ap, format);
+      nbytes = evxprintf (&b, &bsize, stackbuf, -1, format, ap);
+      va_end (ap);
+      if (b != stackbuf)
+       xfree (b);
+    }
+
+  if (INT_MAX < nbytes)
+    {
+#ifdef EOVERFLOW
+      errno = EOVERFLOW;
+#else
+      errno = EDOM;
+#endif
+      return -1;
+    }
+  return nbytes;
+}
+#endif
 \f
 int
-emacs_open (path, oflag, mode)
-     const char *path;
-     int oflag, mode;
+emacs_open (const char *path, int oflag, int mode)
 {
   register int rtnval;
 
@@ -2473,8 +1862,7 @@ emacs_open (path, oflag, mode)
 }
 
 int
-emacs_close (fd)
-     int fd;
+emacs_close (int fd)
 {
   int did_retry = 0;
   register int rtnval;
@@ -2492,13 +1880,27 @@ emacs_close (fd)
   return rtnval;
 }
 
-int
-emacs_read (fildes, buf, nbyte)
-     int fildes;
-     char *buf;
-     unsigned int nbyte;
+/* Maximum number of bytes to read or write in a single system call.
+   This works around a serious bug in Linux kernels before 2.6.16; see
+   <https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=612839>.
+   It's likely to work around similar bugs in other operating systems, so do it
+   on all platforms.  Round INT_MAX down to a page size, with the conservative
+   assumption that page sizes are at most 2**18 bytes (any kernel with a
+   page size larger than that shouldn't have the bug).  */
+#ifndef MAX_RW_COUNT
+#define MAX_RW_COUNT (INT_MAX >> 18 << 18)
+#endif
+
+/* Read from FILEDESC to a buffer BUF with size NBYTE, retrying if interrupted.
+   Return the number of bytes read, which might be less than NBYTE.
+   On error, set errno and return -1.  */
+ptrdiff_t
+emacs_read (int fildes, char *buf, ptrdiff_t nbyte)
 {
-  register int rtnval;
+  register ssize_t rtnval;
+
+  /* There is no need to check against MAX_RW_COUNT, since no caller ever
+     passes a size that large to emacs_read.  */
 
   while ((rtnval = read (fildes, buf, nbyte)) == -1
         && (errno == EINTR))
@@ -2506,21 +1908,22 @@ emacs_read (fildes, buf, nbyte)
   return (rtnval);
 }
 
-int
-emacs_write (fildes, buf, nbyte)
-     int fildes;
-     const char *buf;
-     unsigned int nbyte;
+/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
+   or if a partial write occurs.  Return the number of bytes written, setting
+   errno if this is less than NBYTE.  */
+ptrdiff_t
+emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
 {
-  register int rtnval, bytes_written;
+  ssize_t rtnval;
+  ptrdiff_t bytes_written;
 
   bytes_written = 0;
 
   while (nbyte > 0)
     {
-      rtnval = write (fildes, buf, nbyte);
+      rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
 
-      if (rtnval == -1)
+      if (rtnval < 0)
        {
          if (errno == EINTR)
            {
@@ -2532,15 +1935,32 @@ emacs_write (fildes, buf, nbyte)
              continue;
            }
          else
-           return (bytes_written ? bytes_written : -1);
+           break;
        }
 
       buf += rtnval;
       nbyte -= rtnval;
       bytes_written += rtnval;
     }
+
   return (bytes_written);
 }
+
+static struct allocator const emacs_norealloc_allocator =
+  { xmalloc, NULL, xfree, memory_full };
+
+/* Get the symbolic link value of FILENAME.  Return a pointer to a
+   NUL-terminated string.  If readlink fails, return NULL and set
+   errno.  If the value fits in INITIAL_BUF, return INITIAL_BUF.
+   Otherwise, allocate memory and return a pointer to that memory.  If
+   memory allocation fails, diagnose and fail without returning.  If
+   successful, store the length of the symbolic link into *LINKLEN.  */
+char *
+emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
+{
+  return careadlinkat (AT_FDCWD, filename, initial_buf, READLINK_BUFSIZE,
+                      &emacs_norealloc_allocator, careadlinkatcwd);
+}
 \f
 #ifdef USG
 /*
@@ -2563,19 +1983,18 @@ emacs_write (fildes, buf, nbyte)
  *     under error conditions.
  */
 
+#ifndef HAVE_GETWD
+
 #ifndef MAXPATHLEN
 /* In 4.1, param.h fails to define this.  */
 #define MAXPATHLEN 1024
 #endif
 
-#ifndef HAVE_GETWD
-
 char *
-getwd (pathname)
-     char *pathname;
+getwd (char *pathname)
 {
   char *npath, *spath;
-  extern char *getcwd ();
+  extern char *getcwd (char *, size_t);
 
   BLOCK_INPUT;                 /* getcwd uses malloc */
   spath = npath = getcwd ((char *) 0, MAXPATHLEN);
@@ -2604,9 +2023,8 @@ getwd (pathname)
 
 #ifndef HAVE_RENAME
 
-rename (from, to)
-     const char *from;
-     const char *to;
+int
+rename (const char *from, const char *to)
 {
   if (access (from, 0) == 0)
     {
@@ -2621,84 +2039,23 @@ rename (from, to)
 #endif
 
 
-#if defined(HPUX) && !defined(HAVE_PERROR)
+#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.  */
 
-perror ()
+void
+perror (void)
 {
 }
 #endif /* HPUX and not HAVE_PERROR */
 
-#ifndef HAVE_DUP2
-
-/*
- *     Emulate BSD dup2.  First close newd if it already exists.
- *     Then, attempt to dup oldd.  If not successful, call dup2 recursively
- *     until we are, then close the unsuccessful ones.
- */
-
-dup2 (oldd, newd)
-     int oldd;
-     int newd;
-{
-  register int fd, ret;
-
-  emacs_close (newd);
-
-#ifdef F_DUPFD
-  return fcntl (oldd, F_DUPFD, newd);
-#else
-  fd = dup (old);
-  if (fd == -1)
-    return -1;
-  if (fd == new)
-    return new;
-  ret = dup2 (old,new);
-  emacs_close (fd);
-  return ret;
-#endif
-}
-
-#endif /* not HAVE_DUP2 */
-
-/*
- *     Gettimeofday.  Simulate as much as possible.  Only accurate
- *     to nearest second.  Emacs doesn't use tzp so ignore it for now.
- *     Only needed when subprocesses are defined.
- */
-
-#ifdef subprocesses
-#ifndef HAVE_GETTIMEOFDAY
-#ifdef HAVE_TIMEVAL
-
-/* ARGSUSED */
-int
-gettimeofday (tp, tzp)
-     struct timeval *tp;
-     struct timezone *tzp;
-{
-  extern long time ();
-
-  tp->tv_sec = time ((long *)0);
-  tp->tv_usec = 0;
-  if (tzp != 0)
-    tzp->tz_minuteswest = -1;
-  return 0;
-}
-
-#endif
-#endif
-#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
-
 /*
  *     This function will go away as soon as all the stubs fixed. (fnf)
  */
 
 void
-croak (badfunc)
-     char *badfunc;
+croak (char *badfunc)
 {
   printf ("%s not yet implemented\r\n", badfunc);
   reset_all_sys_modes ();
@@ -2709,7 +2066,7 @@ croak (badfunc)
 \f
 /* Directory routines for systems that don't have them. */
 
-#ifdef SYSV_SYSTEM_DIR
+#ifdef HAVE_DIRENT_H
 
 #include <dirent.h>
 
@@ -2721,37 +2078,51 @@ closedir (DIR *dirp /* stream from opendir */)
   int rtnval;
 
   rtnval = emacs_close (dirp->dd_fd);
-
-  /* Some systems (like Solaris) allocate the buffer and the DIR all
-     in one block.  Why in the world are we freeing this ourselves
-     anyway?  */
-#if ! defined (SOLARIS2)
-  xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
-#endif
   xfree ((char *) dirp);
 
   return rtnval;
 }
 #endif /* not HAVE_CLOSEDIR */
-#endif /* SYSV_SYSTEM_DIR */
+#endif /* HAVE_DIRENT_H */
 
 \f
+/* Return a struct timeval that is roughly equivalent to T.
+   Use the least timeval not less than T.
+   Return an extremal value if the result would overflow.  */
+struct timeval
+make_timeval (EMACS_TIME t)
+{
+  struct timeval tv;
+  tv.tv_sec = t.tv_sec;
+  tv.tv_usec = t.tv_nsec / 1000;
+
+  if (t.tv_nsec % 1000 != 0)
+    {
+      if (tv.tv_usec < 999999)
+       tv.tv_usec++;
+      else if (tv.tv_sec < TYPE_MAXIMUM (time_t))
+       {
+         tv.tv_sec++;
+         tv.tv_usec = 0;
+       }
+    }
+
+  return tv;
+}
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+   ATIME and MTIME, respectively.
+   FD must be either negative -- in which case it is ignored --
+   or a file descriptor that is open on FILE.
+   If FD is nonnegative, then FILE can be NULL.  */
 int
-set_file_times (filename, atime, mtime)
-     const char *filename;
-     EMACS_TIME atime, mtime;
-{
-#ifdef HAVE_UTIMES
-  struct timeval tv[2];
-  tv[0] = atime;
-  tv[1] = mtime;
-  return utimes (filename, tv);
-#else /* not HAVE_UTIMES */
-  struct utimbuf utb;
-  utb.actime = EMACS_SECS (atime);
-  utb.modtime = EMACS_SECS (mtime);
-  return utime (filename, &utb);
-#endif /* not HAVE_UTIMES */
+set_file_times (int fd, const char *filename,
+               EMACS_TIME atime, EMACS_TIME mtime)
+{
+  struct timespec timespec[2];
+  timespec[0] = atime;
+  timespec[1] = mtime;
+  return fdutimens (fd, filename, timespec);
 }
 \f
 /* mkdir and rmdir functions, for systems which don't have them.  */
@@ -2776,11 +2147,10 @@ set_file_times (filename, atime, mtime)
  * Make a directory.
  */
 int
-mkdir (dpath, dmode)
-     char *dpath;
-     int dmode;
+mkdir (char *dpath, int dmode)
 {
-  int cpid, status, fd;
+  pid_t cpid;
+  int status, fd;
   struct stat statbuf;
 
   if (stat (dpath, &statbuf) == 0)
@@ -2836,8 +2206,7 @@ mkdir (dpath, dmode)
 
 #ifndef HAVE_RMDIR
 int
-rmdir (dpath)
-     char *dpath;
+rmdir (char *dpath)
 {
   int cpid, status, fd;
   struct stat statbuf;
@@ -2882,58 +2251,9 @@ rmdir (dpath)
 #endif /* !HAVE_RMDIR */
 
 \f
-#ifndef BSTRING
-
-#ifndef bzero
-
-void
-bzero (b, length)
-     register char *b;
-     register int length;
-{
-  while (length-- > 0)
-    *b++ = 0;
-}
-
-#endif /* no bzero */
-#endif /* BSTRING */
-
-#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
-#undef bcopy
-
-/* Saying `void' requires a declaration, above, where bcopy is used
-   and that declaration causes pain for systems where bcopy is a macro.  */
-bcopy (b1, b2, length)
-     register char *b1;
-     register char *b2;
-     register int length;
-{
-  while (length-- > 0)
-    *b2++ = *b1++;
-}
-#endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
-
-#ifndef BSTRING
-#ifndef bcmp
-int
-bcmp (b1, b2, length)  /* This could be a macro! */
-     register char *b1;
-     register char *b2;
-     register int length;
-{
-  while (length-- > 0)
-    if (*b1++ != *b2++)
-      return 1;
-
-  return 0;
-}
-#endif /* no bcmp */
-#endif /* not BSTRING */
-\f
 #ifndef HAVE_STRSIGNAL
 char *
-strsignal (code)
-     int code;
+strsignal (int code)
 {
   char *signame = 0;
 
@@ -2947,9 +2267,10 @@ strsignal (code)
 }
 #endif /* HAVE_STRSIGNAL */
 \f
-#ifdef HAVE_TERMIOS
+#ifndef DOS_NT
 /* For make-serial-process  */
-int serial_open (char *port)
+int
+serial_open (char *port)
 {
   int fd = -1;
 
@@ -2975,14 +2296,12 @@ int serial_open (char *port)
 
   return fd;
 }
-#endif /* TERMIOS  */
-
-#ifdef HAVE_TERMIOS
 
 #if !defined (HAVE_CFMAKERAW)
 /* Workaround for targets which are missing cfmakeraw.  */
 /* Pasted from man page.  */
-static void cfmakeraw (struct termios *termios_p)
+static void
+cfmakeraw (struct termios *termios_p)
 {
     termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
     termios_p->c_oflag &= ~OPOST;
@@ -2994,7 +2313,8 @@ static void cfmakeraw (struct termios *termios_p)
 
 #if !defined (HAVE_CFSETSPEED)
 /* Workaround for targets which are missing cfsetspeed.  */
-static int cfsetspeed (struct termios *termios_p, speed_t vitesse)
+static int
+cfsetspeed (struct termios *termios_p, speed_t vitesse)
 {
   return (cfsetispeed (termios_p, vitesse)
          + cfsetospeed (termios_p, vitesse));
@@ -3004,7 +2324,7 @@ static int cfsetspeed (struct termios *termios_p, speed_t vitesse)
 /* For serial-process-configure  */
 void
 serial_configure (struct Lisp_Process *p,
-                     Lisp_Object contact)
+                 Lisp_Object contact)
 {
   Lisp_Object childp2 = Qnil;
   Lisp_Object tem = Qnil;
@@ -3034,7 +2354,8 @@ serial_configure (struct Lisp_Process *p,
   CHECK_NUMBER (tem);
   err = cfsetspeed (&attr, XINT (tem));
   if (err != 0)
-    error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
+    error ("cfsetspeed(%"pI"d) failed: %s", XINT (tem),
+          emacs_strerror (errno));
   childp2 = Fplist_put (childp2, QCspeed, tem);
 
   /* Configure bytesize.  */
@@ -3047,7 +2368,7 @@ serial_configure (struct Lisp_Process *p,
   CHECK_NUMBER (tem);
   if (XINT (tem) != 7 && XINT (tem) != 8)
     error (":bytesize must be nil (8), 7, or 8");
-  summary[0] = XINT(tem) + '0';
+  summary[0] = XINT (tem) + '0';
 #if defined (CSIZE) && defined (CS7) && defined (CS8)
   attr.c_cflag &= ~CSIZE;
   attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
@@ -3162,7 +2483,7 @@ serial_configure (struct Lisp_Process *p,
   p->childp = childp2;
 
 }
-#endif /* TERMIOS  */
+#endif /* not DOS_NT  */
 \f
 /* System depended enumeration of and access to system processes a-la ps(1).  */
 
@@ -3171,7 +2492,7 @@ serial_configure (struct Lisp_Process *p,
 /* Process enumeration and access via /proc.  */
 
 Lisp_Object
-list_system_processes ()
+list_system_processes (void)
 {
   Lisp_Object procdir, match, proclist, next;
   struct gcpro gcpro1, gcpro2;
@@ -3200,12 +2521,58 @@ list_system_processes ()
   return proclist;
 }
 
+#elif defined BSD_SYSTEM
+
+Lisp_Object
+list_system_processes (void)
+{
+#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};
+#endif
+  size_t len;
+  struct kinfo_proc *procs;
+  size_t i;
+
+  struct gcpro gcpro1;
+  Lisp_Object proclist = Qnil;
+
+  if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0)
+    return proclist;
+
+  procs = xmalloc (len);
+  if (sysctl (mib, 3, procs, &len, NULL, 0) != 0)
+    {
+      xfree (procs);
+      return proclist;
+    }
+
+  GCPRO1 (proclist);
+  len /= sizeof (struct kinfo_proc);
+  for (i = 0; i < len; i++)
+    {
+#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
+    }
+  UNGCPRO;
+
+  xfree (procs);
+
+  return  proclist;
+}
+
 /* The WINDOWSNT implementation is in w32.c.
    The MSDOS implementation is in dosfns.c.  */
 #elif !defined (WINDOWSNT) && !defined (MSDOS)
 
 Lisp_Object
-list_system_processes ()
+list_system_processes (void)
 {
   return Qnil;
 }
@@ -3213,60 +2580,82 @@ list_system_processes ()
 #endif /* !defined (WINDOWSNT) */
 
 #ifdef GNU_LINUX
-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;
+static EMACS_TIME
+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 ();
+  if (LONG_MAX - 1 <= ULLONG_MAX / EMACS_TIME_RESOLUTION
+      || frac <= ULLONG_MAX / EMACS_TIME_RESOLUTION)
+    ns = frac * EMACS_TIME_RESOLUTION / hz;
   else
-    *usec = tval / (hz / 1000000);
+    {
+      /* This is reachable only in the unlikely case that HZ * HZ
+        exceeds ULLONG_MAX.  It calculates an approximation that is
+        guaranteed to be in range.  */
+      long hz_per_ns = (hz / EMACS_TIME_RESOLUTION
+                       + (hz % EMACS_TIME_RESOLUTION != 0));
+      ns = frac / hz_per_ns;
+    }
+
+  EMACS_SET_SECS_NSECS (t, s, ns);
+  return t;
 }
 
 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));
+  EMACS_TIME t = time_from_jiffies (tval, hz);
+  return make_lisp_time (t);
 }
 
-static void
-get_up_time (time_t *sec, unsigned *usec)
+static EMACS_TIME
+get_up_time (void)
 {
   FILE *fup;
+  EMACS_TIME up;
 
-  *sec = *usec = 0;
+  EMACS_SET_SECS_NSECS (up, 0, 0);
 
   BLOCK_INPUT;
   fup = fopen ("/proc/uptime", "r");
 
   if (fup)
     {
-      double uptime, idletime;
+      unsigned long long upsec, upfrac, idlesec, idlefrac;
+      int upfrac_start, upfrac_end, idlefrac_start, idlefrac_end;
 
-      /* 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))
+      if (fscanf (fup, "%llu.%n%llu%n %llu.%n%llu%n",
+                 &upsec, &upfrac_start, &upfrac, &upfrac_end,
+                 &idlesec, &idlefrac_start, &idlefrac, &idlefrac_end)
+         == 4)
        {
-         *sec = uptime;
-         *usec = (uptime - *sec) * 1000000;
+         if (TYPE_MAXIMUM (time_t) < upsec)
+           {
+             upsec = TYPE_MAXIMUM (time_t);
+             upfrac = EMACS_TIME_RESOLUTION - 1;
+           }
+         else
+           {
+             int upfraclen = upfrac_end - upfrac_start;
+             for (; upfraclen < LOG10_EMACS_TIME_RESOLUTION; upfraclen++)
+               upfrac *= 10;
+             for (; LOG10_EMACS_TIME_RESOLUTION < upfraclen; upfraclen--)
+               upfrac /= 10;
+             upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1);
+           }
+         EMACS_SET_SECS_NSECS (up, upsec, upfrac);
        }
       fclose (fup);
     }
   UNBLOCK_INPUT;
+
+  return up;
 }
 
 #define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
@@ -3355,26 +2744,28 @@ 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;
-  size_t cmdsize = 0, cmdline_size;
+  ptrdiff_t cmdline_size;
   unsigned char c;
-  int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
-  unsigned long long utime, stime, cutime, cstime, start;
-  long priority, nice, rss;
+  printmax_t proc_id;
+  int ppid, pgrp, sess, tty, tpgid, thcount;
+  uid_t uid;
+  gid_t gid;
+  unsigned long long u_time, s_time, cutime, cstime, start;
+  long priority, niceness, rss;
   unsigned long minflt, majflt, cminflt, cmajflt, vsize;
-  time_t sec;
-  unsigned usec;
-  EMACS_TIME tnow, tstart, tboot, telapsed,ttotal;
+  EMACS_TIME tnow, tstart, tboot, telapsed, us_time;
   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/%u", proc_id);
+  CONS_TO_INTEGER (pid, pid_t, proc_id);
+  sprintf (procfn, "/proc/%"pMd, proc_id);
   if (stat (procfn, &st) < 0)
     return attrs;
 
@@ -3382,9 +2773,7 @@ system_process_attributes (Lisp_Object pid)
 
   /* 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);
+  attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
   BLOCK_INPUT;
   pw = getpwuid (uid);
   UNBLOCK_INPUT;
@@ -3392,8 +2781,7 @@ system_process_attributes (Lisp_Object pid)
     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);
+  attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
   BLOCK_INPUT;
   gr = getgrgid (gid);
   UNBLOCK_INPUT;
@@ -3404,7 +2792,7 @@ system_process_attributes (Lisp_Object pid)
   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)
+  if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof (procbuf) - 1)) > 0)
     {
       procbuf[nread] = '\0';
       p = procbuf;
@@ -3422,11 +2810,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,
@@ -3441,8 +2824,8 @@ system_process_attributes (Lisp_Object pid)
          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);
+                 &u_time, &s_time, &cutime, &cstime,
+                 &priority, &niceness, &thcount, &start, &vsize, &rss);
          {
            char state_str[2];
 
@@ -3470,13 +2853,14 @@ system_process_attributes (Lisp_Object pid)
          if (clocks_per_sec < 0)
            clocks_per_sec = 100;
          attrs = Fcons (Fcons (Qutime,
-                               ltime_from_jiffies (utime, clocks_per_sec)),
+                               ltime_from_jiffies (u_time, clocks_per_sec)),
                         attrs);
          attrs = Fcons (Fcons (Qstime,
-                               ltime_from_jiffies (stime, clocks_per_sec)),
+                               ltime_from_jiffies (s_time, clocks_per_sec)),
                         attrs);
          attrs = Fcons (Fcons (Qtime,
-                               ltime_from_jiffies (stime+utime, clocks_per_sec)),
+                               ltime_from_jiffies (s_time + u_time,
+                                                   clocks_per_sec)),
                         attrs);
          attrs = Fcons (Fcons (Qcutime,
                                ltime_from_jiffies (cutime, clocks_per_sec)),
@@ -3488,38 +2872,21 @@ system_process_attributes (Lisp_Object pid)
                                ltime_from_jiffies (cstime+cutime, clocks_per_sec)),
                         attrs);
          attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
-         attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
+         attrs = Fcons (Fcons (Qnice, make_number (niceness)), 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);
+         telapsed = get_up_time ();
          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);
+         tstart = time_from_jiffies (start, clocks_per_sec);
          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 (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);
-         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 (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)
+                 / EMACS_TIME_TO_DOUBLE (telapsed));
          if (pcpu > 1.0)
            pcpu = 1.0;
          attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
@@ -3537,8 +2904,12 @@ system_process_attributes (Lisp_Object pid)
   fd = emacs_open (fn, O_RDONLY, 0);
   if (fd >= 0)
     {
-      for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
+      char ch;
+      for (cmdline_size = 0; cmdline_size < STRING_BYTES_BOUND; cmdline_size++)
        {
+         if (emacs_read (fd, &ch, 1) != 1)
+           break;
+         c = ch;
          if (isspace (c) || c == '\\')
            cmdline_size++;     /* for later quoting, see below */
        }
@@ -3558,7 +2929,7 @@ system_process_attributes (Lisp_Object pid)
              nread = 0;
            }
          /* We don't want trailing null characters.  */
-         for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
+         for (p = cmdline + nread; p > cmdline + 1 && !p[-1]; p--)
            nread--;
          for (p = cmdline; p < cmdline + nread; p++)
            {
@@ -3576,14 +2947,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.  */
@@ -3613,6 +2979,8 @@ system_process_attributes (Lisp_Object pid)
 
 #if PROCFS_FILE_OFFSET_BITS_HACK ==  1
 #define _FILE_OFFSET_BITS 64
+#ifdef _FILE_OFFSET_BITS /* Avoid unused-macro warnings.  */
+#endif
 #endif /* PROCFS_FILE_OFFSET_BITS_HACK ==  1 */
 
 Lisp_Object
@@ -3626,15 +2994,16 @@ system_process_attributes (Lisp_Object pid)
   struct psinfo pinfo;
   int fd;
   ssize_t nread;
-  int proc_id, uid, gid;
+  printmax_t proc_id;
+  uid_t uid;
+  gid_t gid;
   Lisp_Object attrs = Qnil;
   Lisp_Object 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/%u", proc_id);
+  CONS_TO_INTEGER (pid, pid_t, proc_id);
+  sprintf (procfn, "/proc/%"pMd, proc_id);
   if (stat (procfn, &st) < 0)
     return attrs;
 
@@ -3642,9 +3011,7 @@ system_process_attributes (Lisp_Object pid)
 
   /* 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);
+  attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
   BLOCK_INPUT;
   pw = getpwuid (uid);
   UNBLOCK_INPUT;
@@ -3652,8 +3019,7 @@ system_process_attributes (Lisp_Object pid)
     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);
+  attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
   BLOCK_INPUT;
   gr = getgrgid (gid);
   UNBLOCK_INPUT;
@@ -3665,7 +3031,7 @@ system_process_attributes (Lisp_Object pid)
   strcpy (procfn_end, "/psinfo");
   fd = emacs_open (fn, O_RDONLY, 0);
   if (fd >= 0
-      && (nread = read (fd, (char*)&pinfo, sizeof(struct psinfo)) > 0))
+      && (nread = read (fd, (char*)&pinfo, sizeof (struct psinfo)) > 0))
     {
           attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (pinfo.pr_ppid)), attrs);
          attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pinfo.pr_pgid)), attrs);
@@ -3696,33 +3062,20 @@ system_process_attributes (Lisp_Object pid)
                Qcstime
                Are they available? */
 
-         attrs = Fcons (Fcons (Qtime,
-                               list3 (make_number (pinfo.pr_time.tv_sec >> 16),
-                                      make_number (pinfo.pr_time.tv_sec & 0xffff),
-                                      make_number (pinfo.pr_time.tv_nsec))),
-                        attrs);
-
-         attrs = Fcons (Fcons (Qctime,
-                               list3 (make_number (pinfo.pr_ctime.tv_sec >> 16),
-                                      make_number (pinfo.pr_ctime.tv_sec & 0xffff),
-                                      make_number (pinfo.pr_ctime.tv_nsec))),
-                        attrs);
-
+         attrs = Fcons (Fcons (Qtime, make_lisp_time (pinfo.pr_time)), attrs);
+         attrs = Fcons (Fcons (Qctime, make_lisp_time (pinfo.pr_ctime)), attrs);
          attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
          attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
          attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
 
-         attrs = Fcons (Fcons (Qstart,
-                               list3 (make_number (pinfo.pr_start.tv_sec >> 16),
-                                      make_number (pinfo.pr_start.tv_sec & 0xffff),
-                                      make_number (pinfo.pr_start.tv_nsec))),
-                        attrs);
+         attrs = Fcons (Fcons (Qstart, make_lisp_time (pinfo.pr_start)), attrs);
          attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
          attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);
 
-         /* pr_pctcpu and pr_pctmem are encoded as a fixed point 16 bit number in  [0 ... 1].  */
-         attrs = Fcons (Fcons (Qpcpu, (pinfo.pr_pctcpu * 100.0) / (double)0x8000), attrs);
-         attrs = Fcons (Fcons (Qpmem, (pinfo.pr_pctmem * 100.0) / (double)0x8000), attrs);
+         /* pr_pctcpu and pr_pctmem are unsigned integers in the
+            range 0 .. 2**15, representing 0.0 .. 1.0.  */
+         attrs = Fcons (Fcons (Qpcpu, make_float (100.0 / 0x8000 * pinfo.pr_pctcpu)), attrs);
+         attrs = Fcons (Fcons (Qpmem, make_float (100.0 / 0x8000 * pinfo.pr_pctmem)), attrs);
 
          decoded_cmd
            =  code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname,
@@ -3743,6 +3096,196 @@ system_process_attributes (Lisp_Object pid)
   return attrs;
 }
 
+#elif defined __FreeBSD__
+
+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;
+}
+
+static Lisp_Object
+make_lisp_timeval (struct timeval t)
+{
+  return make_lisp_time (timeval_to_EMACS_TIME (t));
+}
+
+Lisp_Object
+system_process_attributes (Lisp_Object pid)
+{
+  int proc_id;
+  int pagesize = getpagesize ();
+  int npages;
+  int fscale;
+  struct passwd *pw;
+  struct group  *gr;
+  char *ttyname;
+  size_t len;
+  char args[MAXPATHLEN];
+  EMACS_TIME t, now;
+
+  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
+  struct kinfo_proc proc;
+  size_t proclen = sizeof proc;
+
+  struct gcpro gcpro1, gcpro2;
+  Lisp_Object attrs = Qnil;
+  Lisp_Object decoded_comm;
+
+  CHECK_NUMBER_OR_FLOAT (pid);
+  CONS_TO_INTEGER (pid, int, proc_id);
+  mib[3] = proc_id;
+
+  if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0)
+    return attrs;
+
+  GCPRO2 (attrs, decoded_comm);
+
+  attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs);
+
+  BLOCK_INPUT;
+  pw = getpwuid (proc.ki_uid);
+  UNBLOCK_INPUT;
+  if (pw)
+    attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
+
+  attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (proc.ki_svgid)), attrs);
+
+  BLOCK_INPUT;
+  gr = getgrgid (proc.ki_svgid);
+  UNBLOCK_INPUT;
+  if (gr)
+    attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
+
+  decoded_comm = code_convert_string_norecord
+    (make_unibyte_string (proc.ki_comm, strlen (proc.ki_comm)),
+     Vlocale_coding_system, 0);
+
+  attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
+  {
+    char state[2] = {'\0', '\0'};
+    switch (proc.ki_stat)
+      {
+      case SRUN:
+       state[0] = 'R';
+       break;
+
+      case SSLEEP:
+       state[0] = 'S';
+       break;
+
+      case SLOCK:
+       state[0] = 'D';
+       break;
+
+      case SZOMB:
+       state[0] = 'Z';
+       break;
+
+      case SSTOP:
+       state[0] = 'T';
+       break;
+      }
+    attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
+  }
+
+  attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (proc.ki_ppid)), attrs);
+  attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.ki_pgid)), attrs);
+  attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (proc.ki_sid)),  attrs);
+
+  BLOCK_INPUT;
+  ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR);
+  UNBLOCK_INPUT;
+  if (ttyname)
+    attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs);
+
+  attrs = Fcons (Fcons (Qtpgid,   make_fixnum_or_float (proc.ki_tpgid)), attrs);
+  attrs = Fcons (Fcons (Qminflt,  make_fixnum_or_float (proc.ki_rusage.ru_minflt)), attrs);
+  attrs = Fcons (Fcons (Qmajflt,  make_fixnum_or_float (proc.ki_rusage.ru_majflt)), attrs);
+  attrs = Fcons (Fcons (Qcminflt, make_number (proc.ki_rusage_ch.ru_minflt)), attrs);
+  attrs = Fcons (Fcons (Qcmajflt, make_number (proc.ki_rusage_ch.ru_majflt)), attrs);
+
+  attrs = Fcons (Fcons (Qutime, make_lisp_timeval (proc.ki_rusage.ru_utime)),
+                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));
+  attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
+
+  attrs = Fcons (Fcons (Qcutime,
+                       make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
+                attrs);
+  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));
+  attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs);
+
+  attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (proc.ki_numthreads)),
+                attrs);
+  attrs = Fcons (Fcons (Qpri,   make_number (proc.ki_pri.pri_native)), attrs);
+  attrs = Fcons (Fcons (Qnice,  make_number (proc.ki_nice)), attrs);
+  attrs = Fcons (Fcons (Qstart, make_lisp_timeval (proc.ki_start)), attrs);
+  attrs = Fcons (Fcons (Qvsize, make_number (proc.ki_size >> 10)), attrs);
+  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));
+  attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
+
+  len = sizeof fscale;
+  if (sysctlbyname ("kern.fscale", &fscale, &len, NULL, 0) == 0)
+    {
+      double pcpu;
+      fixpt_t ccpu;
+      len = sizeof ccpu;
+      if (sysctlbyname ("kern.ccpu", &ccpu, &len, NULL, 0) == 0)
+       {
+         pcpu = (100.0 * proc.ki_pctcpu / fscale
+                 / (1 - exp (proc.ki_swtime * log ((double) ccpu / fscale))));
+         attrs = Fcons (Fcons (Qpcpu, make_fixnum_or_float (pcpu)), attrs);
+       }
+    }
+
+  len = sizeof npages;
+  if (sysctlbyname ("hw.availpages", &npages, &len, NULL, 0) == 0)
+    {
+      double pmem = (proc.ki_flag & P_INMEM
+                    ? 100.0 * proc.ki_rssize / npages
+                    : 0);
+      attrs = Fcons (Fcons (Qpmem, make_fixnum_or_float (pmem)), attrs);
+    }
+
+  mib[2] = KERN_PROC_ARGS;
+  len = MAXPATHLEN;
+  if (sysctl (mib, 4, args, &len, NULL, 0) == 0)
+    {
+      int i;
+      for (i = 0; i < len; i++)
+       {
+         if (! args[i] && i < len - 1)
+           args[i] = ' ';
+       }
+
+      decoded_comm =
+       (code_convert_string_norecord
+        (make_unibyte_string (args, strlen (args)),
+         Vlocale_coding_system, 0));
+
+      attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
+    }
+
+  UNGCPRO;
+  return attrs;
+}
+
 /* The WINDOWSNT implementation is in w32.c.
    The MSDOS implementation is in dosfns.c.  */
 #elif !defined (WINDOWSNT) && !defined (MSDOS)
@@ -3754,7 +3297,3 @@ system_process_attributes (Lisp_Object pid)
 }
 
 #endif /* !defined (WINDOWSNT) */
-
-
-/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
-   (do not change this comment) */