Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 2003d1abfa0c20ee77815f0da33e2c1c > files > 167

glibc-2.5-49.el5_5.5.src.rpm

2007-07-16  Jakub Jelinek  <jakub@redhat.com>

	* libio/iopopen.c (_IO_new_proc_open): Don't close child_std_end
	if one of proc_file_chain streams has that fileno.
	* stdio-common/Makefile (tests): Add tst-popen2.
	* stdio-common/tst-popen2.c: New test.

--- libc/libio/iopopen.c	14 Sep 2004 04:24:45 -0000	1.33
+++ libc/libio/iopopen.c	19 Jul 2007 17:02:07 -0000	1.34
@@ -169,7 +170,15 @@ _IO_new_proc_open (fp, command, mode)
          popen() calls that remain open in the parent process are closed
 	 in the new child process." */
       for (p = proc_file_chain; p; p = p->next)
-	_IO_close (_IO_fileno ((_IO_FILE *) p));
+	{
+	  int fd = _IO_fileno ((_IO_FILE *) p);
+
+	  /* If any stream from previous popen() calls has fileno
+	     child_std_end, it has been already closed by the dup2 syscall
+	     above.  */
+	  if (fd != child_std_end)
+	    _IO_close (fd);
+	}
 
       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
       _IO__exit (127);
--- libc/stdio-common/Makefile	8 Jul 2007 04:41:08 -0000	1.104
+++ libc/stdio-common/Makefile	19 Jul 2007 17:02:55 -0000	1.105
@@ -54,7 +54,8 @@ tests := tstscanf test_rdwr test-popen t
 	 tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \
 	 tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 bug15 \
 	 tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
-	 tst-fwrite bug16 bug17 tst-sprintf2 bug18 bug18a bug19 bug19a
+	 tst-fwrite bug16 bug17 tst-sprintf2 bug18 bug18a bug19 bug19a \
+	 tst-popen2
 
 test-srcs = tst-unbputc tst-printf
 
--- libc/stdio-common/tst-popen2.c	1 Jan 1970 00:00:00 -0000
+++ libc/stdio-common/tst-popen2.c	19 Jul 2007 17:02:43 -0000	1.1
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+  int fd = dup (fileno (stdout));
+  if (fd <= 1)
+    {
+      puts ("dup failed");
+      return 1;
+    }
+
+  FILE *f1 = fdopen (fd, "w");
+  if (f1 == NULL)
+    {
+      printf ("fdopen failed: %m\n");
+      return 1;
+    }
+
+  fclose (stdout);
+
+  FILE *f2 = popen ("echo test1", "r");
+  if (f2 == NULL)
+    {
+      fprintf (f1, "1st popen failed: %m\n");
+      return 1;
+    }
+  FILE *f3 = popen ("echo test2", "r");
+  if (f2 == NULL || f3 == NULL)
+    {
+      fprintf (f1, "2nd popen failed: %m\n");
+      return 1;
+    }
+
+  char *line = NULL;
+  size_t len = 0;
+  int result = 0;
+  if (getline (&line, &len, f2) != 6)
+    {
+      fputs ("could not read line from 1st popen\n", f1);
+      result = 1;
+    }
+  else if (strcmp (line, "test1\n") != 0)
+    {
+      fprintf (f1, "read \"%s\"\n", line);
+      result = 1;
+    }
+
+  if (getline (&line, &len, f2) != -1)
+    {
+      fputs ("second getline did not return -1\n", f1);
+      result = 1;
+    }
+
+  if (getline (&line, &len, f3) != 6)
+    {
+      fputs ("could not read line from 2nd popen\n", f1);
+      result = 1;
+    }
+  else if (strcmp (line, "test2\n") != 0)
+    {
+      fprintf (f1, "read \"%s\"\n", line);
+      result = 1;
+    }
+
+  if (getline (&line, &len, f3) != -1)
+    {
+      fputs ("second getline did not return -1\n", f1);
+      result = 1;
+    }
+
+  int ret = pclose (f2);
+  if (ret != 0)
+    {
+      fprintf (f1, "1st pclose returned %d\n", ret);
+      result = 1;
+    }
+
+  ret = pclose (f3);
+  if (ret != 0)
+    {
+      fprintf (f1, "2nd pclose returned %d\n", ret);
+      result = 1;
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"