Make file descriptors close-on-exec when possible.
[bpt/emacs.git] / src / sysdep.c
index 606a5b0..faca7fa 100644 (file)
@@ -22,7 +22,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define SYSTIME_INLINE EXTERN_INLINE
 
 #include <execinfo.h>
-#include <stdio.h>
+#include "sysstdio.h"
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #include <grp.h>
@@ -38,9 +38,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "sysselect.h"
 #include "blockinput.h"
 
-#ifdef BSD_SYSTEM
-#include <sys/param.h>
-#include <sys/sysctl.h>
+#if defined DARWIN_OS || defined __FreeBSD__
+# include <sys/sysctl.h>
 #endif
 
 #ifdef __FreeBSD__
@@ -69,9 +68,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
 #include "msdos.h"
-#include <sys/param.h>
 #endif
 
+#include <sys/param.h>
 #include <sys/file.h>
 #include <fcntl.h>
 
@@ -283,7 +282,7 @@ get_child_status (pid_t child, int *status, int options, bool interruptible)
      reap an unwanted process by mistake.  For example, invoking
      waitpid (-1, ...) can mess up glib by reaping glib's subprocesses,
      so that another thread running glib won't find them.  */
-  eassert (0 < child);
+  eassert (child > 0);
 
   while ((pid = waitpid (child, status, options)) < 0)
     {
@@ -544,8 +543,6 @@ sys_subshell (void)
 #endif
        }
 
-      close_process_descs ();  /* Close Emacs's pipes/ptys */
-
 #ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
       {
        char *epwd = getenv ("PWD");
@@ -1290,10 +1287,9 @@ reset_sys_modes (struct tty_display_info *tty_out)
   if (tty_out->terminal->reset_terminal_modes_hook)
     tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
 
-#ifdef BSD_SYSTEM
   /* Avoid possible loss of output when changing terminal modes.  */
-  fsync (fileno (tty_out->output));
-#endif
+  while (fdatasync (fileno (tty_out->output)) != 0 && errno == EINTR)
+    continue;
 
 #ifndef DOS_NT
 #ifdef F_SETOWN
@@ -1632,6 +1628,8 @@ deliver_thread_signal (int sig, signal_handler_t handler)
 # undef sys_siglist
 # ifdef _sys_siglist
 #  define sys_siglist _sys_siglist
+# elif HAVE_DECL___SYS_SIGLIST
+#  define sys_siglist __sys_siglist
 # else
 #  define sys_siglist my_sys_siglist
 static char const *sys_siglist[NSIG];
@@ -2151,15 +2149,53 @@ emacs_abort (void)
 }
 #endif
 
+/* Open FILE for Emacs use, using open flags OFLAG and mode MODE.
+   Arrange for subprograms to not inherit the file descriptor.
+   Prefer a method that is multithread-safe, if available.
+   Do not fail merely because the open was interrupted by a signal.
+   Allow the user to quit.  */
+
 int
-emacs_open (const char *path, int oflag, int mode)
+emacs_open (const char *file, int oflags, int mode)
 {
-  register int rtnval;
-
-  while ((rtnval = open (path, oflag, mode)) == -1
-        && (errno == EINTR))
+  int fd;
+  oflags |= O_CLOEXEC;
+  while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
     QUIT;
-  return (rtnval);
+  if (! O_CLOEXEC && 0 <= fd)
+    fcntl (fd, F_SETFD, FD_CLOEXEC);
+  return fd;
+}
+
+/* Open FILE as a stream for Emacs use, with mode MODE.
+   Act like emacs_open with respect to threads, signals, and quits.  */
+
+FILE *
+emacs_fopen (char const *file, char const *mode)
+{
+  int fd, omode, oflags;
+  int bflag = 0;
+  char const *m = mode;
+
+  switch (*m++)
+    {
+    case 'r': omode = O_RDONLY; oflags = 0; break;
+    case 'w': omode = O_WRONLY; oflags = O_CREAT | O_TRUNC; break;
+    case 'a': omode = O_WRONLY; oflags = O_CREAT | O_APPEND; break;
+    default: emacs_abort ();
+    }
+
+  while (*m)
+    switch (*m++)
+      {
+      case '+': omode = O_RDWR; break;
+      case 'b': bflag = O_BINARY; break;
+      case 't': bflag = O_TEXT; break;
+      default: /* Ignore.  */ break;
+      }
+
+  fd = emacs_open (file, omode | oflags | bflag, 0666);
+  return fd < 0 ? 0 : fdopen (fd, mode);
 }
 
 int
@@ -2541,12 +2577,12 @@ list_system_processes (void)
   return proclist;
 }
 
-#elif defined BSD_SYSTEM
+#elif defined DARWIN_OS || defined __FreeBSD__
 
 Lisp_Object
 list_system_processes (void)
 {
-#if defined DARWIN_OS || defined __NetBSD__ || defined __OpenBSD__
+#ifdef DARWIN_OS
   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
 #else
   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
@@ -2572,10 +2608,8 @@ list_system_processes (void)
   len /= sizeof (struct kinfo_proc);
   for (i = 0; i < len; i++)
     {
-#if defined DARWIN_OS || defined __NetBSD__
+#ifdef DARWIN_OS
       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
@@ -2639,7 +2673,7 @@ get_up_time (void)
   EMACS_TIME up = make_emacs_time (0, 0);
 
   block_input ();
-  fup = fopen ("/proc/uptime", "r");
+  fup = emacs_fopen ("/proc/uptime", "r");
 
   if (fup)
     {
@@ -2684,7 +2718,7 @@ procfs_ttyname (int rdev)
   char name[PATH_MAX];
 
   block_input ();
-  fdev = fopen ("/proc/tty/drivers", "r");
+  fdev = emacs_fopen ("/proc/tty/drivers", "r");
 
   if (fdev)
     {
@@ -2695,7 +2729,7 @@ procfs_ttyname (int rdev)
 
       while (!feof (fdev) && !ferror (fdev))
        {
-         if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
+         if (fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor) >= 3
              && major == MAJOR (rdev))
            {
              minor_beg = strtoul (minor, &endp, 0);
@@ -2726,7 +2760,7 @@ procfs_get_total_memory (void)
   unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
 
   block_input ();
-  fmem = fopen ("/proc/meminfo", "r");
+  fmem = emacs_fopen ("/proc/meminfo", "r");
 
   if (fmem)
     {
@@ -2735,7 +2769,7 @@ procfs_get_total_memory (void)
 
       while (!feof (fmem) && !ferror (fmem))
        {
-         if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
+         if (fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value) >= 2
              && strcmp (entry_name, "MemTotal:") == 0)
            {
              retval = entry_value;