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:
parent
56dbf99329
commit
a051160962
@ -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>
|
2009-08-17 Craig Howland <howland@LGSInnovations.com>
|
||||||
|
|
||||||
* libc/string/wcsncpy.c (wcsncpy): Re-write function based on small
|
* libc/string/wcsncpy.c (wcsncpy): Re-write function based on small
|
||||||
|
@ -51,7 +51,8 @@ endif # USE_LIBTOOL
|
|||||||
|
|
||||||
include $(srcdir)/../../Makefile.shared
|
include $(srcdir)/../../Makefile.shared
|
||||||
|
|
||||||
CHEWOUT_FILES =
|
CHEWOUT_FILES = \
|
||||||
|
popen.def
|
||||||
|
|
||||||
SUFFIXES = .def
|
SUFFIXES = .def
|
||||||
|
|
||||||
@ -63,8 +64,8 @@ CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str
|
|||||||
|
|
||||||
TARGETDOC = ../tmp.texi
|
TARGETDOC = ../tmp.texi
|
||||||
|
|
||||||
# No doc for posix.
|
doc: $(CHEWOUT_FILES)
|
||||||
doc:
|
cat $(srcdir)/posix.tex >> $(TARGETDOC)
|
||||||
|
|
||||||
AM_CFLAGS = -D_GNU_SOURCE
|
AM_CFLAGS = -D_GNU_SOURCE
|
||||||
|
|
||||||
|
@ -32,6 +32,53 @@
|
|||||||
* SUCH DAMAGE.
|
* 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
|
#ifndef _NO_POPEN
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
@ -59,21 +106,21 @@ static struct pid {
|
|||||||
struct pid *next;
|
struct pid *next;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
} *pidlist;
|
} *pidlist;
|
||||||
|
|
||||||
FILE *
|
FILE *
|
||||||
_DEFUN(popen, (program, type),
|
_DEFUN(popen, (program, type),
|
||||||
const char *program _AND
|
const char *program _AND
|
||||||
const char *type)
|
const char *type)
|
||||||
{
|
{
|
||||||
struct pid *cur;
|
struct pid *cur, *last;
|
||||||
FILE *iop;
|
FILE *iop;
|
||||||
int pdes[2], pid;
|
int pdes[2], pid;
|
||||||
|
|
||||||
if ((*type != 'r' && *type != 'w')
|
if ((*type != 'r' && *type != 'w')
|
||||||
|| (type[1]
|
|| (type[1]
|
||||||
#ifdef __CYGWIN__
|
#ifdef HAVE_FCNTL
|
||||||
&& (type[2] || (type[1] != 'b' && type[1] != 't'))
|
&& (type[2] || (type[1] != 'e'))
|
||||||
#endif
|
#endif
|
||||||
)) {
|
)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@ -111,12 +158,11 @@ _DEFUN(popen, (program, type),
|
|||||||
}
|
}
|
||||||
(void)close(pdes[1]);
|
(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);
|
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);
|
_exit(127);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
@ -131,9 +177,10 @@ _DEFUN(popen, (program, type),
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_FCNTL
|
#ifdef HAVE_FCNTL
|
||||||
/* Hide pipe from future popens; assume fcntl can't fail. */
|
/* Mark pipe cloexec if requested. */
|
||||||
fcntl (fileno (iop), F_SETFD,
|
if (type[1] == 'e')
|
||||||
fcntl (fileno (iop), F_GETFD, 0) | FD_CLOEXEC);
|
fcntl (fileno (iop), F_SETFD,
|
||||||
|
fcntl (fileno (iop), F_GETFD, 0) | FD_CLOEXEC);
|
||||||
#endif /* HAVE_FCNTL */
|
#endif /* HAVE_FCNTL */
|
||||||
|
|
||||||
/* Link into list of file descriptors. */
|
/* Link into list of file descriptors. */
|
||||||
@ -177,7 +224,7 @@ _DEFUN(pclose, (iop),
|
|||||||
else
|
else
|
||||||
last->next = cur->next;
|
last->next = cur->next;
|
||||||
free(cur);
|
free(cur);
|
||||||
|
|
||||||
return (pid == -1 ? -1 : pstat);
|
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
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user