summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2009-08-18 16:43:21 +0000
committerEric Blake <eblake@redhat.com>2009-08-18 16:43:21 +0000
commita0511609626a3eabf8fa4a2b7769b9096ae4caa6 (patch)
treeb5adebbe7d765f4a16d177b2ef4ddcc118b48707
parent56dbf993295cf7189bb50a9cbbf5ac3b14694103 (diff)
downloadcygnal-a0511609626a3eabf8fa4a2b7769b9096ae4caa6.tar.gz
cygnal-a0511609626a3eabf8fa4a2b7769b9096ae4caa6.tar.bz2
cygnal-a0511609626a3eabf8fa4a2b7769b9096ae4caa6.zip
Improve popen compatibility with glibc.
* libc/posix/popen.c (popen): The 2006-08-22 change to use FD_CLOEXEC disagrees with other implementations; instead, use pidlist to work even when fcntl is not available. Meanwhile, support the 'e' modifier to set CLOEXEC, as in glibc. Drop cygwin-specific code, now that cygwin has its own version. * libc/posix/Makefile.am (CHEWOUT_FILES): Document popen. * libc/posix/posix.tex: New file.
-rw-r--r--newlib/ChangeLog11
-rw-r--r--newlib/libc/posix/Makefile.am7
-rw-r--r--newlib/libc/posix/popen.c75
-rw-r--r--newlib/libc/posix/posix.tex13
4 files changed, 89 insertions, 17 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index f49232ea0..655116b62 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,14 @@
+2009-08-18 Eric Blake <ebb9@byu.net>
+
+ Improve popen compatibility with glibc.
+ * libc/posix/popen.c (popen): The 2006-08-22 change to use
+ FD_CLOEXEC disagrees with other implementations; instead, use
+ pidlist to work even when fcntl is not available. Meanwhile,
+ support the 'e' modifier to set CLOEXEC, as in glibc. Drop
+ cygwin-specific code, now that cygwin has its own version.
+ * libc/posix/Makefile.am (CHEWOUT_FILES): Document popen.
+ * libc/posix/posix.tex: New file.
+
2009-08-17 Craig Howland <howland@LGSInnovations.com>
* libc/string/wcsncpy.c (wcsncpy): Re-write function based on small
diff --git a/newlib/libc/posix/Makefile.am b/newlib/libc/posix/Makefile.am
index c8c1a1254..fa20dd725 100644
--- a/newlib/libc/posix/Makefile.am
+++ b/newlib/libc/posix/Makefile.am
@@ -51,7 +51,8 @@ endif # USE_LIBTOOL
include $(srcdir)/../../Makefile.shared
-CHEWOUT_FILES =
+CHEWOUT_FILES = \
+ popen.def
SUFFIXES = .def
@@ -63,8 +64,8 @@ CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str
TARGETDOC = ../tmp.texi
-# No doc for posix.
-doc:
+doc: $(CHEWOUT_FILES)
+ cat $(srcdir)/posix.tex >> $(TARGETDOC)
AM_CFLAGS = -D_GNU_SOURCE
diff --git a/newlib/libc/posix/popen.c b/newlib/libc/posix/popen.c
index d09c9c54f..accf76c98 100644
--- a/newlib/libc/posix/popen.c
+++ b/newlib/libc/posix/popen.c
@@ -32,6 +32,53 @@
* SUCH DAMAGE.
*/
+/*
+FUNCTION
+<<popen>>, <<pclose>>---tie a stream to a command string
+
+INDEX
+ popen
+INDEX
+ pclose
+
+ANSI_SYNOPSIS
+ #include <stdio.h>
+ FILE *popen(char *<[s]>, char *<[mode]>);
+
+ int pclose(FILE *<[f]>);
+
+DESCRIPTION
+Use <<popen>> to create a stream to a child process executing a
+command string <<*<[s]>>> as processed by <</bin/sh>> on your system.
+The argument <[mode]> must start with either `<<r>>', where the stream
+reads from the child's <<stdout>>, or `<<w>>', where the stream writes
+to the child's <<stdin>>. As an extension, <[mode]> may also contain
+`<<e>>' to set the close-on-exec bit of the parent's file descriptor.
+The stream created by <<popen>> must be closed by <<pclose>> to avoid
+resource leaks.
+
+Streams created by prior calls to <<popen>> are not visible in
+subsequent <<popen>> children, regardless of the close-on-exec bit.
+
+Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
+available.
+
+RETURNS
+<<popen>> returns a file stream opened with the specified <[mode]>,
+or <<NULL>> if a child process could not be created. <<pclose>>
+returns -1 if the stream was not created by <<popen>> or if the
+application used <<wait>> or similar to steal the status; otherwise
+it returns the exit status of the child which can be interpreted
+in the same manner as a status obtained by <<waitpid>>.
+
+PORTABILITY
+POSIX.2 requires <<popen>> and <<pclose>>, but only specifies a mode
+of just <<r>> or <<w>>. Where <<sh>> is found is left unspecified.
+
+Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
+<<_wait_r>>, <<pipe>>, <<fcntl>>, <<sbrk>>.
+*/
+
#ifndef _NO_POPEN
#if defined(LIBC_SCCS) && !defined(lint)
@@ -59,21 +106,21 @@ static struct pid {
struct pid *next;
FILE *fp;
pid_t pid;
-} *pidlist;
-
+} *pidlist;
+
FILE *
_DEFUN(popen, (program, type),
const char *program _AND
const char *type)
{
- struct pid *cur;
+ struct pid *cur, *last;
FILE *iop;
int pdes[2], pid;
if ((*type != 'r' && *type != 'w')
|| (type[1]
-#ifdef __CYGWIN__
- && (type[2] || (type[1] != 'b' && type[1] != 't'))
+#ifdef HAVE_FCNTL
+ && (type[2] || (type[1] != 'e'))
#endif
)) {
errno = EINVAL;
@@ -111,12 +158,11 @@ _DEFUN(popen, (program, type),
}
(void)close(pdes[1]);
}
+ /* Close all fd's created by prior popen. */
+ for (last = NULL, cur = pidlist; cur;
+ last = cur, cur = cur->next)
+ (void)close (fileno (cur->fp));
execl(_PATH_BSHELL, "sh", "-c", program, NULL);
-#ifdef __CYGWIN__
- /* On cygwin32, we may not have /bin/sh. In that
- case, try to find sh on PATH. */
- execlp("sh", "sh", "-c", program, NULL);
-#endif
_exit(127);
/* NOTREACHED */
}
@@ -131,9 +177,10 @@ _DEFUN(popen, (program, type),
}
#ifdef HAVE_FCNTL
- /* Hide pipe from future popens; assume fcntl can't fail. */
- fcntl (fileno (iop), F_SETFD,
- fcntl (fileno (iop), F_GETFD, 0) | FD_CLOEXEC);
+ /* Mark pipe cloexec if requested. */
+ if (type[1] == 'e')
+ fcntl (fileno (iop), F_SETFD,
+ fcntl (fileno (iop), F_GETFD, 0) | FD_CLOEXEC);
#endif /* HAVE_FCNTL */
/* Link into list of file descriptors. */
@@ -177,7 +224,7 @@ _DEFUN(pclose, (iop),
else
last->next = cur->next;
free(cur);
-
+
return (pid == -1 ? -1 : pstat);
}
diff --git a/newlib/libc/posix/posix.tex b/newlib/libc/posix/posix.tex
new file mode 100644
index 000000000..4c85fce5b
--- /dev/null
+++ b/newlib/libc/posix/posix.tex
@@ -0,0 +1,13 @@
+@node Posix
+@chapter Posix Functions
+
+This chapter groups several utility functions specified by POSIX, but
+not by C. Each function documents which header to use.
+
+@menu
+* popen:: Create a stream tied to a child process
+@end menu
+
+@page
+@include posix/popen.def
+