about summary refs log tree commit diff
path: root/nis/nss_compat/compat-initgroups.c
diff options
context:
space:
mode:
Diffstat (limited to 'nis/nss_compat/compat-initgroups.c')
-rw-r--r--nis/nss_compat/compat-initgroups.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/nis/nss_compat/compat-initgroups.c b/nis/nss_compat/compat-initgroups.c
index 70403a0785..fd16475ea9 100644
--- a/nis/nss_compat/compat-initgroups.c
+++ b/nis/nss_compat/compat-initgroups.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2003, 2004, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2004, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
 
@@ -30,6 +30,7 @@
 #include <sys/param.h>
 #include <nsswitch.h>
 #include <bits/libc-lock.h>
+#include <kernel-features.h>
 
 static service_user *ni;
 /* Type of the lookup function.  */
@@ -74,6 +75,19 @@ struct ent_t
 typedef struct ent_t ent_t;
 
 
+/* Positive if O_CLOEXEC is supported, negative if it is not supported,
+   zero if it is still undecided.  This variable is shared with the
+   other compat functions.  */
+#ifdef __ASSUME_O_CLOEXEC
+# define __compat_have_cloexec 1
+#else
+# ifdef O_CLOEXEC
+extern int __compat_have_cloexec;
+# else
+#  define __compat_have_cloexec -1
+# endif
+#endif
+
 /* Prototypes for local functions.  */
 static void blacklist_store_name (const char *, ent_t *);
 static int in_blacklist (const char *, int, ent_t *);
@@ -117,21 +131,35 @@ internal_setgrent (ent_t *ent)
   else
     ent->blacklist.current = 0;
 
-  ent->stream = fopen ("/etc/group", "rm");
+  ent->stream = fopen ("/etc/group", "rme");
 
   if (ent->stream == NULL)
     status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
   else
     {
       /* We have to make sure the file is  `closed on exec'.  */
-      int result, flags;
+      int result = 0;
 
-      result = flags = fcntl (fileno_unlocked (ent->stream), F_GETFD, 0);
-      if (result >= 0)
+      if (__compat_have_cloexec <= 0)
 	{
-	  flags |= FD_CLOEXEC;
-	  result = fcntl (fileno_unlocked (ent->stream), F_SETFD, flags);
+	  int flags;
+	  result = flags = fcntl (fileno_unlocked (ent->stream), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+#if defined O_CLOEXEC && !defined __ASSUME_O_CLOEXEC
+	      if (__compat_have_cloexec == 0)
+		__compat_have_cloexec = (flags & FD_CLOEXEC) ? 1 : -1;
+
+	      if (__compat_have_cloexec < 0)
+#endif
+		{
+		  flags |= FD_CLOEXEC;
+		  result = fcntl (fileno_unlocked (ent->stream), F_SETFD,
+				  flags);
+		}
+	    }
 	}
+
       if (result < 0)
 	{
 	  /* Something went wrong.  Close the stream and return a