mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-11 07:40:05 +00:00
8d57beeab1
Thu Jan 23 04:06:42 1997 Ulrich Drepper <drepper@cygnus.com> * Make-dist (.PHONY: dist): Remove duplicate declaration. (README): Depend on version.h not version.c. * Makefile (README): Depend on version.h not version.c. * Makeconfig (inst_libdir, inst_slibdir, inst_includedir, inst_datadir, inst_zonedir, inst_localedir, inst_i18ndir, inst_bindir, inst_sbindir, inst_infodir, inst_sysconfdir): New variables. Same as variable withough inst_ but prepended with $(install_root). (localtime-time): Use $(inst_sysconfdir) not $(sysconfdir). * Makefile (install-others): Use $(inst_includedir). (gnu/stabs.h, gnu/lib-names.h): Use $(inst_includedir). * Makerules (tons of install rules): Use inst_% variables. * elf/Makefile: Likewise. * hurd/Makefile: Likewise. * intl/Makefile: Likewise. * manual/Makefile: Likewise. * po/Makefile: Likewise. * sunrpc/Makefile: Likewise. * sysdeps/mach/hurd/Makefile: Likewise. * sysdeps/standalone/i386/force_cpu386/Makefile: Likewise. * time/Makefile: Likewise. * config.make.in: Revert patch from Sat Jan 18 22:15:26 1997, leave install_root in place. * gnu-versions.h (_GNU_GETOPT_INTERFACE_VERSION): Define to 2. * posix/getopt.c (GETOPT_INTERFACE_VERSION): Define to 2. * posix/getopt1.c (GETOPT_INTERFACE_VERSION): Define to 2. * elf/Makefile [yes==$(has-ldconfig)]: Correct dependencies of ldconfig. (CFLAGS-dl-load.c): New variable, avoid gcc warning. * sysdeps/mach/hurd/configure.in: Add _LIBC_REENTRENT to DEFINES. * sysdeps/mach/hurd/getdents.c: Update copyright. De-ANSI-declfy. * sysdeps/stub/getdents.c: Likewise. Correct return value. * sysdeps/unix/getdents.c: Likewise. * sysdeps/unix/sysv/getdents.c: Likewise. * sysdeps/unix/readdir.c: Update copyright. * sysdeps/unix/bsd/sony/newsos4/Makefile: Correct ifeq arguments. * sysdeps/unix/bsd/sun/sunos4/Makefile: Likewise. * sysdeps/unix/sysv/Makefile: Likewise. * sysdeps/unix/sysv/linux/Makefile: Likewise. * sysdeps/unix/sysv/linux/alpha/Makefile: Likewise. * sysdeps/unix/sysv/linux/i386/Makefile: Likewise. * sysdeps/unix/sysv/linux/Dist: Don't distribute kernel_termios.h, but sys/kernel_termios.h. * sysdeps/unix/sysv/linux/alpha/Dist: Likewise. * sysdeps/unix/sysv/linux/Makefile [$(subdir)==termios] (sysdep_headers): Add sys/kernel_termios.h. * sysdeps/unix/sysv/linux/kernel_termios.h: Moved to... * sysdeps/unix/sysv/linux/sys/kernel_termios.h: ...here. * sysdeps/unix/sysv/linux/sys/tcgetattr.c: Use __kernel_termios and __KERNEL_NCCS instead of kernel_termios and KERNEL_NCCS resp. * sysdeps/unix/sysv/linux/alpha/ioctls.h: New file. * sysdeps/unix/sysv/linux/getdents.c: Correct problems with alignment. * sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove getdents. Reported by Eirik Fuller <eirik@netcom.com>. * time/Banner: Removed. Wrong and unnecessary information. It's now in... * time/README: New file. * time/Makefile (distribute): Remove Banner, add README. Wed Jan 22 13:19:56 1997 Richard Henderson <rth@tamu.edu> * sysdeps/unix/sysv/linux/alpha/ioperm.c (platforms): Add Sable. (init_iosys): Recognize /etc/alpha_systype as a four-tuple for the purpose of supporting brand new systems. (*): The type of iosys variables should be iosys_t. 1997-01-22 Paul Eggert <eggert@twinsun.com> * strftime.c (_strftime_copytm): New function, to work around Solaris 2.5 tzset bug. Wed Jan 22 23:05:14 1997 Ulrich Drepper <drepper@cygnus.com> * sysdeps/mach/hurd/vdprintf.c: Complete de-ANSI-declfication. * sysdeps/posix/pipestream.c (writedecl): Fix typo. Reported by Marcus G. Daniels <marcus@shannon.sysc.pdx.edu>. Wed Jan 22 13:58:56 1997 Andreas Jaeger <aj@arthur.pfalz.de> * elf/Makefile (CFLAGS-dl-load.c): New Variable to keep gcc silent since name_copy is initialized. Wed Jan 22 16:58:12 1997 Ulrich Drepper <drepper@cygnus.com> * stdio-common/Makefile (tests): Remove scanf11. * stdio-common/scanf11.c: Removed. * stdio-common/vfscanf.c Revert patch of Thu Jan 16 23:39:25 1997. Although the Corrigendum 1 describes the result as implemented the even more recent Amendement 1 seconds the position of ISO C:1990 where the %n directive has no effect on the assignment count. * stdio-common/bug10.c: Likewise. * stdio-common/scanf1.c: Likewise. * stdio-common/scanf3.c: Likewise. * stdio-common/scanf10.c: Likewise. * stdio-common/tstdiomisc.c: Likewise. * new-malloc/obstack.h: Don't define malloc using bcopy if malloc is not available. This leads to problems since bcopy does not return a value. Instead define _obstack_memcpy based on memcpy or bcopy. This name isn't used outside obstack.h and so no problems from using the memcpy function in a file including obstack.h can result. Reported by Martin Trapp <trapp@ipd.info.uni-karlsruhe.de>. Tue Jan 21 18:35:55 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * misc/regexp.h (compile): Fix typos. Tue Jan 21 01:01:59 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * sysdeps/unix/sysv/linux/sys/procfs.h (struct elf_prpsinfo): Fix type of pr_{pid,ppid,pgrp,sid} fields. * sysdeps/unix/sysv/linux/alpha/sys/procfs.h (struct elf_prpsinfo): Likewise.
226 lines
6.1 KiB
C
226 lines
6.1 KiB
C
/* Copyright (C) 1991, 1992, 1993, 1996, 1997 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
|
||
modify it under the terms of the GNU Library General Public License as
|
||
published by the Free Software Foundation; either version 2 of the
|
||
License, or (at your option) any later version.
|
||
|
||
The GNU C Library is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
Library General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Library General Public
|
||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||
Boston, MA 02111-1307, USA. */
|
||
|
||
#include <errno.h>
|
||
#include <stddef.h>
|
||
#include <signal.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <sys/types.h>
|
||
#include <sys/wait.h>
|
||
#include <unistd.h>
|
||
#include <fcntl.h>
|
||
|
||
#define SH_PATH "/bin/sh" /* Shell to run. */
|
||
#define SH_NAME "sh" /* Name to give it. */
|
||
|
||
/* Structure describing a popen child. */
|
||
struct child
|
||
{
|
||
pid_t pid; /* PID of the child. */
|
||
__ptr_t cookie; /* Original cookie from fdopen. */
|
||
__io_functions funcs; /* Original functions from fdopen. */
|
||
};
|
||
|
||
/* io_functions for pipe streams.
|
||
These all simply call the corresponding
|
||
original function with the original cookie. */
|
||
|
||
#define FUNC(type, name, args) \
|
||
static type __CONCAT(child_,name) args __CONCAT(name,decl) \
|
||
{ \
|
||
struct child *c = (struct child *) cookie; \
|
||
{ \
|
||
__ptr_t cookie = c->cookie; \
|
||
return (*c->funcs.__CONCAT(__,name)) args; \
|
||
} \
|
||
}
|
||
|
||
#define readdecl void *cookie; register char *buf; register size_t n;
|
||
FUNC (int, read, (cookie, buf, n))
|
||
#define writedecl void *cookie; register const char *buf; register size_t n;
|
||
FUNC (int, write, (cookie, buf, n))
|
||
#define seekdecl void *cookie; fpos_t *pos; int whence;
|
||
FUNC (int, seek, (cookie, pos, whence))
|
||
#define closedecl void *cookie;
|
||
FUNC (int, close, (cookie))
|
||
#define filenodecl void *cookie;
|
||
FUNC (int, fileno, (cookie))
|
||
|
||
static const __io_functions child_funcs
|
||
= { child_read, child_write, child_seek, child_close, child_fileno };
|
||
|
||
/* Open a new stream that is a one-way pipe to a
|
||
child process running the given shell command. */
|
||
FILE *
|
||
popen (command, mode)
|
||
const char *command;
|
||
const char *mode;
|
||
{
|
||
pid_t pid;
|
||
int pipedes[2];
|
||
FILE *stream;
|
||
struct child *child;
|
||
|
||
if (command == NULL || mode == NULL || (*mode != 'r' && *mode != 'w'))
|
||
{
|
||
__set_errno (EINVAL);
|
||
return NULL;
|
||
}
|
||
|
||
/* Create the pipe. */
|
||
if (pipe (pipedes) < 0)
|
||
return NULL;
|
||
|
||
/* Fork off the child. */
|
||
pid = __vfork ();
|
||
if (pid == (pid_t) -1)
|
||
{
|
||
/* The fork failed. */
|
||
(void) close (pipedes[0]);
|
||
(void) close (pipedes[1]);
|
||
return NULL;
|
||
}
|
||
else if (pid == (pid_t) 0)
|
||
{
|
||
/* We are the child side. Make the write side of
|
||
the pipe be stdin or the read side be stdout. */
|
||
|
||
const char *new_argv[4];
|
||
|
||
if ((*mode == 'w' ? dup2(pipedes[STDIN_FILENO], STDIN_FILENO) :
|
||
dup2 (pipedes[STDOUT_FILENO], STDOUT_FILENO)) < 0)
|
||
_exit (127);
|
||
|
||
/* Close the pipe descriptors. */
|
||
(void) close (pipedes[STDIN_FILENO]);
|
||
(void) close (pipedes[STDOUT_FILENO]);
|
||
|
||
/* Exec the shell. */
|
||
new_argv[0] = SH_NAME;
|
||
new_argv[1] = "-c";
|
||
new_argv[2] = command;
|
||
new_argv[3] = NULL;
|
||
(void) execve (SH_PATH, (char *const *) new_argv, environ);
|
||
/* Die if it failed. */
|
||
_exit (127);
|
||
}
|
||
|
||
/* We are the parent side. */
|
||
|
||
/* Close the irrelevant side of the pipe and open the relevant side as a
|
||
new stream. Mark our side of the pipe to close on exec, so new children
|
||
won't see it. */
|
||
if (*mode == 'r')
|
||
{
|
||
(void) close (pipedes[STDOUT_FILENO]);
|
||
(void) fcntl (pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
|
||
stream = fdopen (pipedes[STDIN_FILENO], mode);
|
||
}
|
||
else
|
||
{
|
||
(void) close (pipedes[STDIN_FILENO]);
|
||
(void) fcntl (pipedes[STDOUT_FILENO], F_SETFD, FD_CLOEXEC);
|
||
stream = fdopen (pipedes[STDOUT_FILENO], mode);
|
||
}
|
||
|
||
if (stream == NULL)
|
||
goto error;
|
||
|
||
child = (struct child *) malloc (sizeof (struct child));
|
||
if (child == NULL)
|
||
goto error;
|
||
|
||
{
|
||
/* Make sure STREAM has its functions set before
|
||
we try to squirrel them away in CHILD. */
|
||
extern void __stdio_check_funcs __P ((FILE *));
|
||
__stdio_check_funcs (stream);
|
||
}
|
||
|
||
child->pid = pid;
|
||
child->cookie = stream->__cookie;
|
||
child->funcs = stream->__io_funcs;
|
||
stream->__cookie = (void *) child;
|
||
stream->__io_funcs = child_funcs;
|
||
stream->__ispipe = 1;
|
||
return stream;
|
||
|
||
error:
|
||
{
|
||
/* The stream couldn't be opened or the child structure couldn't be
|
||
allocated. Kill the child and close the other side of the pipe. */
|
||
int save = errno;
|
||
(void) kill (pid, SIGKILL);
|
||
if (stream == NULL)
|
||
(void) close (pipedes[*mode == 'r' ? STDOUT_FILENO : STDIN_FILENO]);
|
||
else
|
||
(void) fclose (stream);
|
||
#ifndef NO_WAITPID
|
||
(void) waitpid (pid, (int *) NULL, 0);
|
||
#else
|
||
{
|
||
pid_t dead;
|
||
do
|
||
dead = wait ((int *) NULL);
|
||
while (dead > 0 && dead != pid);
|
||
}
|
||
#endif
|
||
__set_errno (save);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
/* Close a stream opened by popen and return its status.
|
||
Returns -1 if the stream was not opened by popen. */
|
||
int
|
||
pclose (stream)
|
||
register FILE *stream;
|
||
{
|
||
struct child *c;
|
||
pid_t pid, dead;
|
||
int status;
|
||
|
||
if (!__validfp (stream) || !stream->__ispipe)
|
||
{
|
||
__set_errno (EINVAL);
|
||
return -1;
|
||
}
|
||
|
||
c = (struct child *) stream->__cookie;
|
||
pid = c->pid;
|
||
stream->__cookie = c->cookie;
|
||
stream->__io_funcs = c->funcs;
|
||
free ((void *) c);
|
||
stream->__ispipe = 0;
|
||
if (fclose (stream))
|
||
return -1;
|
||
|
||
#ifndef NO_WAITPID
|
||
dead = waitpid (pid, &status, 0);
|
||
#else
|
||
do
|
||
dead = wait (&status);
|
||
while (dead > 0 && dead != pid);
|
||
#endif
|
||
if (dead != pid)
|
||
status = -1;
|
||
|
||
return status;
|
||
}
|