* alloc.c (pure_bytes_used_lisp, pure_bytes_used_non_lisp):
[bpt/emacs.git] / src / sysdep.c
index a57b8c0..ba296a2 100644 (file)
@@ -26,9 +26,7 @@ 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 */
 #include <unistd.h>
 
 #include <allocator.h>
@@ -296,15 +294,13 @@ init_baud_rate (int fd)
 int wait_debugging EXTERNALLY_VISIBLE;
 
 #ifndef MSDOS
-/* 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 (int pid)
+static void
+wait_for_termination_1 (pid_t pid, int interruptible)
 {
   while (1)
     {
-#if defined (BSD_SYSTEM) || defined (HPUX)
+#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. */
@@ -339,9 +335,27 @@ wait_for_termination (int pid)
       sigsuspend (&empty_mask);
 #endif /* not WINDOWSNT */
 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
+      if (interruptible)
+       QUIT;
     }
 }
 
+/* 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
  *      (may flush input as well; it does not matter the way we use it)
@@ -1109,8 +1123,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;
@@ -1123,8 +1136,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;
@@ -1137,16 +1149,28 @@ 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
@@ -1302,7 +1326,7 @@ setup_pty (int 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);
@@ -1475,7 +1499,7 @@ sys_signal (int signal_number, signal_handler_t action)
      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;
@@ -1508,7 +1532,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);
 }
 
@@ -1516,7 +1540,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);
 }
 
@@ -1524,7 +1548,7 @@ 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);
 }
 
@@ -1757,33 +1781,26 @@ seed_random (long int 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
+EMACS_INT
 get_random (void)
 {
-  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_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;
@@ -1794,6 +1811,45 @@ 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)
+    {
+      errno = EOVERFLOW;
+      return -1;
+    }
+  return nbytes;
+}
+#endif
 \f
 int
 emacs_open (const char *path, int oflag, int mode)
@@ -1839,8 +1895,8 @@ emacs_close (int fd)
 /* 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.  */
-EMACS_INT
-emacs_read (int fildes, char *buf, EMACS_INT nbyte)
+ptrdiff_t
+emacs_read (int fildes, char *buf, ptrdiff_t nbyte)
 {
   register ssize_t rtnval;
 
@@ -1856,11 +1912,11 @@ emacs_read (int fildes, char *buf, EMACS_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.  */
-EMACS_INT
-emacs_write (int fildes, const char *buf, EMACS_INT nbyte)
+ptrdiff_t
+emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
 {
   ssize_t rtnval;
-  EMACS_INT bytes_written;
+  ptrdiff_t bytes_written;
 
   bytes_written = 0;
 
@@ -1984,7 +2040,7 @@ rename (const char *from, const char *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.  */
@@ -1995,37 +2051,6 @@ 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.
- */
-
-int
-dup2 (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.
@@ -2126,7 +2151,8 @@ set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime)
 int
 mkdir (char *dpath, int dmode)
 {
-  int cpid, status, fd;
+  pid_t cpid;
+  int status, fd;
   struct stat statbuf;
 
   if (stat (dpath, &statbuf) == 0)
@@ -2227,59 +2253,6 @@ rmdir (char *dpath)
 #endif /* !HAVE_RMDIR */
 
 \f
-#ifndef HAVE_MEMSET
-void *
-memset (void *b, int n, size_t length)
-{
-  unsigned char *p = b;
-  while (length-- > 0)
-    *p++ = n;
-  return b;
-}
-#endif /* !HAVE_MEMSET */
-
-#ifndef HAVE_MEMCPY
-void *
-memcpy (void *b1, void *b2, size_t length)
-{
-  unsigned char *p1 = b1, *p2 = b2;
-  while (length-- > 0)
-    *p1++ = *p2++;
-  return b1;
-}
-#endif /* !HAVE_MEMCPY */
-
-#ifndef HAVE_MEMMOVE
-void *
-memmove (void *b1, void *b2, size_t length)
-{
-  unsigned char *p1 = b1, *p2 = b2;
-  if (p1 < p2 || p1 >= p2 + length)
-    while (length-- > 0)
-      *p1++ = *p2++;
-  else
-    {
-      p1 += length;
-      p2 += length;
-      while (length-- > 0)
-       *--p1 = *--p2;
-    }
-  return b1;
-}
-#endif /* !HAVE_MEMCPY */
-
-#ifndef HAVE_MEMCMP
-int
-memcmp (void *b1, void *b2, size_t length)
-{
-  unsigned char *p1 = b1, *p2 = b2;
-  while (length-- > 0)
-    if (*p1++ != *p2++)
-      return p1[-1] < p2[-1] ? -1 : 1;
-  return 0;
-}
-#endif /* !HAVE_MEMCMP */
-\f
 #ifndef HAVE_STRSIGNAL
 char *
 strsignal (int code)
@@ -2707,9 +2680,12 @@ system_process_attributes (Lisp_Object pid)
   ssize_t nread;
   const char *cmd = NULL;
   char *cmdline = NULL;
-  size_t cmdsize = 0, cmdline_size;
+  ptrdiff_t cmdsize = 0, cmdline_size;
   unsigned char c;
-  int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
+  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;
@@ -2720,11 +2696,18 @@ system_process_attributes (Lisp_Object pid)
   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);
+  if (FLOATP (pid))
+    {
+      double v = XFLOAT_DATA (pid);
+      if (! (TYPE_MINIMUM (pid_t) <= v && v < TYPE_MAXIMUM (pid_t) + 1.0))
+       return attrs;
+      proc_id = v;
+    }
+  else
+    proc_id = XINT (pid);
+  sprintf (procfn, "/proc/%"pMd, proc_id);
   if (stat (procfn, &st) < 0)
     return attrs;
 
@@ -2732,9 +2715,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;
@@ -2742,8 +2723,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;
@@ -2889,8 +2869,10 @@ system_process_attributes (Lisp_Object pid)
   if (fd >= 0)
     {
       char ch;
-      for (cmdline_size = 0; emacs_read (fd, &ch, 1) == 1; cmdline_size++)
+      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 */
@@ -2911,7 +2893,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++)
            {
@@ -2981,15 +2963,24 @@ 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);
+  if (FLOATP (pid))
+    {
+      double v = XFLOAT_DATA (pid);
+      if (! (TYPE_MINIMUM (pid_t) <= v && v < TYPE_MAXIMUM (pid_t) + 1.0))
+       return attrs;
+      proc_id = v;
+    }
+  else
+    proc_id = XINT (v);
+  sprintf (procfn, "/proc/%"pMd, proc_id);
   if (stat (procfn, &st) < 0)
     return attrs;
 
@@ -2997,9 +2988,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;
@@ -3007,8 +2996,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;