⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pipestream.c

📁 一个C源代码分析器
💻 C
字号:
/* Copyright (C) 1991, 1992, 1993 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/ormodify it under the terms of the GNU Library General Public License aspublished by the Free Software Foundation; either version 2 of theLicense, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULibrary General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with the GNU C Library; see the file COPYING.LIB.  Ifnot, write to the Free Software Foundation, Inc., 675 Mass Ave,Cambridge, MA 02139, USA.  */#include <ansidecl.h>#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 DEFUN(__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 PTR cookie AND register char *buf AND register size_t nFUNC (int, read, (cookie, buf, n))#define writedecl PTR cookie AND register CONST char *buf AND register size_t nFUNC (int, write, (cookie, buf, n))#define seekdecl PTR cookie AND fpos_t *pos AND int whenceFUNC (int, seek, (cookie, pos, whence))#define closedecl PTR cookieFUNC (int, close, (cookie))#define filenodecl PTR cookieFUNC (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 *DEFUN(popen, (command, mode), CONST char *command AND CONST char *mode){  pid_t pid;  int pipedes[2];  FILE *stream;  struct child *child;  if (command == NULL || mode == NULL || (*mode != 'r' && *mode != 'w'))    {      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 = (PTR) 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    errno = save;    return NULL;  }}/* Close a stream opened by popen and return its status.   Returns -1 if the stream was not opened by popen.  */intDEFUN(pclose, (stream), register FILE *stream){  struct child *c;  pid_t pid, dead;  int status;  if (!__validfp(stream) || !stream->__ispipe)    {      errno = EINVAL;      return -1;    }  c = (struct child *) stream->__cookie;  pid = c->pid;  stream->__cookie = c->cookie;  stream->__io_funcs = c->funcs;  free ((PTR) 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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -