mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 23:00:07 +00:00
* sysdeps/unix/sysv/linux/syscalls.list: Add __pipe2 alias.
* io/pipe2.c: Likewise. * sysdeps/unix/sysv/linux/kernel-features.h: Define __ASSUME_PIPE2 instead of __ASSUME_PACCEPT. * include/unistd.h: Declare __have_pipe2. * libio/iopopen.c: Implement "e" flag. * libio/Makefile (tests): Add tst-popen1. * libio/tst-popen1.c: New file.
This commit is contained in:
parent
11ed3eaed9
commit
d6e0c2a67d
10
ChangeLog
10
ChangeLog
@ -1,5 +1,15 @@
|
||||
2008-07-27 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/syscalls.list: Add __pipe2 alias.
|
||||
* io/pipe2.c: Likewise.
|
||||
* sysdeps/unix/sysv/linux/kernel-features.h: Define __ASSUME_PIPE2
|
||||
instead of __ASSUME_PACCEPT.
|
||||
* include/unistd.h: Declare __have_pipe2.
|
||||
* libio/iopopen.c: Implement "e" flag.
|
||||
* libio/Makefile (tests): Add tst-popen1.
|
||||
* libio/tst-popen1.c: New file.
|
||||
|
||||
|
||||
* sysdeps/unix/sysv/linux/bits/socket.h: Define PF_ISDN and AF_ISDN.
|
||||
* sysdeps/unix/sysv/linux/sparc/bits/socket.h: Likewise.
|
||||
|
||||
|
@ -48,6 +48,7 @@ extern ssize_t __libc_write (int __fd, __const void *__buf, size_t __n);
|
||||
libc_hidden_proto (__libc_write)
|
||||
extern int __pipe (int __pipedes[2]);
|
||||
libc_hidden_proto (__pipe)
|
||||
extern int __pipe2 (int __pipedes[2], int __flags);
|
||||
extern unsigned int __sleep (unsigned int __seconds);
|
||||
extern int __chown (__const char *__file,
|
||||
__uid_t __owner, __gid_t __group);
|
||||
@ -165,4 +166,10 @@ extern int __libc_pause (void);
|
||||
/* Not cancelable variant. */
|
||||
extern int __pause_nocancel (void) attribute_hidden;
|
||||
|
||||
extern int __have_sock_cloexec;
|
||||
/* At lot of other functionality became available at the same time as
|
||||
SOCK_CLOEXEC. Avoid defining separate variables for all of them
|
||||
unless it is really necessary. */
|
||||
#define __have_pipe2 __have_sock_cloexec
|
||||
|
||||
#endif
|
||||
|
@ -25,7 +25,7 @@
|
||||
PIPEDES[1] can be read from PIPEDES[0]. Apply FLAGS to the new
|
||||
file descriptors. Returns 0 if successful, -1 if not. */
|
||||
int
|
||||
pipe2 (pipedes, flags)
|
||||
__pipe2 (pipedes, flags)
|
||||
int pipedes[2];
|
||||
int flags;
|
||||
{
|
||||
@ -38,6 +38,7 @@ pipe2 (pipedes, flags)
|
||||
__set_errno (ENOSYS);
|
||||
return -1;
|
||||
}
|
||||
weak_alias (__pipe2, pipe2)
|
||||
stub_warning (pipe2)
|
||||
|
||||
#include <stub-tag.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 1995-2002,2003,2004,2006,2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1995-2004,2006,2007,2008 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
|
||||
# The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -58,7 +58,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
|
||||
tst-memstream1 tst-memstream2 \
|
||||
tst-wmemstream1 tst-wmemstream2 \
|
||||
bug-memstream1 bug-wmemstream1 \
|
||||
tst-setvbuf1
|
||||
tst-setvbuf1 tst-popen1
|
||||
test-srcs = test-freopen
|
||||
|
||||
all: # Make this the default target; it will be defined in Rules.
|
||||
|
115
libio/iopopen.c
115
libio/iopopen.c
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1993, 1997-2002, 2003, 2004, 2007
|
||||
/* Copyright (C) 1993, 1997-2002, 2003, 2004, 2007, 2008
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Per Bothner <bothner@cygnus.com>.
|
||||
@ -56,15 +56,6 @@ extern _IO_pid_t _IO_fork (void) __THROW;
|
||||
|
||||
#endif /* _IO_HAVE_SYS_WAIT */
|
||||
|
||||
#ifndef _IO_pipe
|
||||
#ifdef _LIBC
|
||||
#define _IO_pipe __pipe
|
||||
#else
|
||||
#define _IO_pipe pipe
|
||||
#endif
|
||||
extern int _IO_pipe (int des[2]) __THROW;
|
||||
#endif
|
||||
|
||||
#ifndef _IO_dup2
|
||||
#ifdef _LIBC
|
||||
#define _IO_dup2 __dup2
|
||||
@ -131,41 +122,99 @@ _IO_new_proc_open (fp, command, mode)
|
||||
volatile int parent_end, child_end;
|
||||
int pipe_fds[2];
|
||||
_IO_pid_t child_pid;
|
||||
|
||||
int do_read = 0;
|
||||
int do_write = 0;
|
||||
int do_cloexec = 0;
|
||||
while (*mode != '\0')
|
||||
switch (*mode++)
|
||||
{
|
||||
case 'r':
|
||||
do_read = 1;
|
||||
break;
|
||||
case 'w':
|
||||
do_write = 1;
|
||||
break;
|
||||
case 'e':
|
||||
do_cloexec = 1;
|
||||
break;
|
||||
default:
|
||||
errout:
|
||||
__set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((do_read ^ do_write) == 0)
|
||||
goto errout;
|
||||
|
||||
if (_IO_file_is_open (fp))
|
||||
return NULL;
|
||||
if (_IO_pipe (pipe_fds) < 0)
|
||||
return NULL;
|
||||
if (mode[0] == 'r' && mode[1] == '\0')
|
||||
|
||||
#ifdef O_CLOEXEC
|
||||
# ifndef __ASSUME_PIPE2
|
||||
if (__have_pipe2 >= 0)
|
||||
# endif
|
||||
{
|
||||
int r = __pipe2 (pipe_fds, O_CLOEXEC);
|
||||
# ifndef __ASSUME_PIPE2
|
||||
if (__have_pipe2 == 0)
|
||||
__have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;
|
||||
|
||||
if (__have_pipe2 > 0)
|
||||
# endif
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#ifndef __ASSUME_PIPE2
|
||||
# ifdef O_CLOEXEC
|
||||
if (__have_pipe2 < 0)
|
||||
# endif
|
||||
if (__pipe (pipe_fds) < 0)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (do_read)
|
||||
{
|
||||
parent_end = pipe_fds[0];
|
||||
child_end = pipe_fds[1];
|
||||
read_or_write = _IO_NO_WRITES;
|
||||
}
|
||||
else if (mode[0] == 'w' && mode[1] == '\0')
|
||||
else
|
||||
{
|
||||
parent_end = pipe_fds[1];
|
||||
child_end = pipe_fds[0];
|
||||
read_or_write = _IO_NO_READS;
|
||||
}
|
||||
else
|
||||
{
|
||||
_IO_close (pipe_fds[0]);
|
||||
_IO_close (pipe_fds[1]);
|
||||
__set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
|
||||
if (child_pid == 0)
|
||||
{
|
||||
int child_std_end = mode[0] == 'r' ? 1 : 0;
|
||||
int child_std_end = do_read ? 1 : 0;
|
||||
struct _IO_proc_file *p;
|
||||
|
||||
#ifndef __ASSUME_PIPE2
|
||||
/* If we have pipe2 the descriptor is marked for close-on-exec. */
|
||||
_IO_close (parent_end);
|
||||
#endif
|
||||
if (child_end != child_std_end)
|
||||
{
|
||||
_IO_dup2 (child_end, child_std_end);
|
||||
#ifndef __ASSUME_PIPE2
|
||||
_IO_close (child_end);
|
||||
#endif
|
||||
}
|
||||
#ifdef O_CLOEXEC
|
||||
else
|
||||
{
|
||||
/* The descriptor is already the one we will use. But it must
|
||||
not be marked close-on-exec. Undo the effects. */
|
||||
# ifndef __ASSUME_PIPE2
|
||||
if (__have_pipe2 > 0)
|
||||
# endif
|
||||
__fcntl (child_end, F_SETFD, 0);
|
||||
}
|
||||
#endif
|
||||
/* POSIX.2: "popen() shall ensure that any streams from previous
|
||||
popen() calls that remain open in the parent process are closed
|
||||
in the new child process." */
|
||||
@ -189,6 +238,28 @@ _IO_new_proc_open (fp, command, mode)
|
||||
_IO_close (parent_end);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (do_cloexec)
|
||||
{
|
||||
#ifndef __ASSUME_PIPE2
|
||||
# ifdef O_CLOEXEC
|
||||
if (__have_pipe2 < 0)
|
||||
# endif
|
||||
__fcntl (parent_end, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef O_CLOEXEC
|
||||
/* Undo the effects of the pipe2 call which set the
|
||||
close-on-exec flag. */
|
||||
# ifndef __ASSUME_PIPE2
|
||||
if (__have_pipe2 > 0)
|
||||
# endif
|
||||
__fcntl (parent_end, F_SETFD, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
_IO_fileno (fp) = parent_end;
|
||||
|
||||
/* Link into proc_file_chain. */
|
||||
|
49
libio/tst-popen1.c
Normal file
49
libio/tst-popen1.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
FILE *fp = popen ("echo hello", "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
puts ("first popen failed");
|
||||
res = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int fd = fileno (fp);
|
||||
if (fcntl (fd, F_GETFD) == FD_CLOEXEC)
|
||||
{
|
||||
puts ("first popen(\"r\") set FD_CLOEXEC");
|
||||
res = 1;
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
fp = popen ("echo hello", "re");
|
||||
if (fp == NULL)
|
||||
{
|
||||
puts ("second popen failed");
|
||||
res = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int fd = fileno (fp);
|
||||
if (fcntl (fd, F_GETFD) != FD_CLOEXEC)
|
||||
{
|
||||
puts ("second popen(\"r\") did not set FD_CLOEXEC");
|
||||
res = 1;
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -505,5 +505,5 @@
|
||||
|| defined __ia64__ || defined __sparc__)
|
||||
# define __ASSUME_SOCK_CLOEXEC 1
|
||||
# define __ASSUME_IN_NONBLOCK 1
|
||||
# define __ASSUME_PACCEPT 1
|
||||
# define __ASSUME_PIPE2 1
|
||||
#endif
|
||||
|
@ -47,7 +47,7 @@ nfsservctl EXTRA nfsservctl i:ipp nfsservctl
|
||||
pause - pause Ci: __libc_pause pause
|
||||
personality EXTRA personality i:i __personality personality
|
||||
pipe - pipe i:f __pipe pipe
|
||||
pipe2 - pipe2 i:fi pipe2
|
||||
pipe2 - pipe2 i:fi __pipe2 pipe2
|
||||
pivot_root EXTRA pivot_root i:ss pivot_root
|
||||
prctl EXTRA prctl i:iiiii __prctl prctl
|
||||
putpmsg - putpmsg i:ippii putpmsg
|
||||
|
Loading…
Reference in New Issue
Block a user