diff options
author | Eric Blake <eblake@redhat.com> | 2009-08-18 20:43:21 +0400 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2009-08-18 20:43:21 +0400 |
commit | a0511609626a3eabf8fa4a2b7769b9096ae4caa6 (patch) | |
tree | b5adebbe7d765f4a16d177b2ef4ddcc118b48707 /newlib | |
parent | 56dbf993295cf7189bb50a9cbbf5ac3b14694103 (diff) |
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.
Diffstat (limited to 'newlib')
-rw-r--r-- | newlib/ChangeLog | 11 | ||||
-rw-r--r-- | newlib/libc/posix/Makefile.am | 7 | ||||
-rw-r--r-- | newlib/libc/posix/popen.c | 75 | ||||
-rw-r--r-- | newlib/libc/posix/posix.tex | 13 |
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 + |