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.
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								newlib/libc/posix/posix.tex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								newlib/libc/posix/posix.tex
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user