Annotation of GNUtools/libg++/libio/iopopen.c, revision 1.1

1.1     ! root        1: /* 
        !             2: Copyright (C) 1993 Free Software Foundation
        !             3: 
        !             4: This file is part of the GNU IO Library.  This library is free
        !             5: software; you can redistribute it and/or modify it under the
        !             6: terms of the GNU General Public License as published by the
        !             7: Free Software Foundation; either version 2, or (at your option)
        !             8: any later version.
        !             9: 
        !            10: This library is distributed in the hope that it will be useful,
        !            11: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            13: GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with GNU CC; see the file COPYING.  If not, write to
        !            17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
        !            18: 
        !            19: As a special exception, if you link this library with files
        !            20: compiled with a GNU compiler to produce an executable, this does not cause
        !            21: the resulting executable to be covered by the GNU General Public License.
        !            22: This exception does not however invalidate any other reasons why
        !            23: the executable file might be covered by the GNU General Public License. */
        !            24: 
        !            25: /*  written by Per Bothner ([email protected]) */
        !            26: 
        !            27: #include "libioP.h"
        !            28: 
        !            29: #if _IO_HAVE_SYS_WAIT
        !            30: #include <signal.h>
        !            31: #include <unistd.h>
        !            32: #ifdef __STDC__
        !            33: /* This is now provided by gcc's fixproto. */
        !            34: #include <stdlib.h>
        !            35: #endif
        !            36: #include <errno.h>
        !            37: #ifndef errno
        !            38: extern int errno;
        !            39: #endif
        !            40: #include <sys/wait.h>
        !            41: 
        !            42: #ifndef _IO_fork
        !            43: #define _IO_fork vfork /* defined in libiberty, if needed */
        !            44: _IO_pid_t _IO_fork();
        !            45: #endif
        !            46: 
        !            47: #endif /* _IO_HAVE_SYS_WAIT */
        !            48: 
        !            49: #ifndef _IO_pipe
        !            50: #define _IO_pipe pipe
        !            51: extern int _IO_pipe();
        !            52: #endif
        !            53: 
        !            54: #ifndef _IO_dup2
        !            55: #define _IO_dup2 dup2
        !            56: extern int _IO_dup2();
        !            57: #endif
        !            58: 
        !            59: #ifndef _IO_waitpid
        !            60: #define _IO_waitpid waitpid
        !            61: #endif
        !            62: 
        !            63: #ifndef _IO_execl
        !            64: #define _IO_execl execl
        !            65: #endif
        !            66: #ifndef _IO__exit
        !            67: #define _IO__exit _exit
        !            68: #endif
        !            69: 
        !            70: struct _IO_proc_file
        !            71: {
        !            72:   struct _IO_FILE_plus _file;
        !            73:   /* Following fields must match those in class procbuf (procbuf.h) */
        !            74:   _IO_pid_t _pid;
        !            75:   struct _IO_proc_file *_next;
        !            76: };
        !            77: typedef struct _IO_proc_file _IO_proc_file;
        !            78: 
        !            79: static struct _IO_proc_file *proc_file_chain = NULL;
        !            80: 
        !            81: _IO_FILE *
        !            82: _IO_proc_open(fp, command, mode)
        !            83:      _IO_FILE* fp;
        !            84:      const char *command;
        !            85:      const char *mode;
        !            86: {
        !            87: #if _IO_HAVE_SYS_WAIT
        !            88:   int read_or_write;
        !            89:   int pipe_fds[2];
        !            90:   int parent_end, child_end;
        !            91:   _IO_pid_t child_pid;
        !            92:   if (_IO_file_is_open(fp))
        !            93:     return NULL;
        !            94:   if (_IO_pipe(pipe_fds) < 0)
        !            95:     return NULL;
        !            96:   if (mode[0] == 'r')
        !            97:     {
        !            98:       parent_end = pipe_fds[0];
        !            99:       child_end = pipe_fds[1];
        !           100:       read_or_write = _IO_NO_WRITES;
        !           101:     }
        !           102:   else
        !           103:     {
        !           104:       parent_end = pipe_fds[1];
        !           105:       child_end = pipe_fds[0];
        !           106:       read_or_write = _IO_NO_READS;
        !           107:     }
        !           108:   ((_IO_proc_file*)fp)->_pid = child_pid = _IO_fork();
        !           109:   if (child_pid == 0)
        !           110:     {
        !           111:       int child_std_end = mode[0] == 'r' ? 1 : 0;
        !           112:       _IO_close(parent_end);
        !           113:       if (child_end != child_std_end)
        !           114:        {
        !           115:          _IO_dup2(child_end, child_std_end);
        !           116:          _IO_close(child_end);
        !           117:        }
        !           118:       /* Posix.2:  "popen() shall ensure that any streams from previous
        !           119:          popen() calls that remain open in the parent process are closed
        !           120:         in the new child process." */
        !           121:       while (proc_file_chain)
        !           122:        {
        !           123:          _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain));
        !           124:          proc_file_chain = proc_file_chain->_next;
        !           125:        }
        !           126: 
        !           127:       _IO_execl("/bin/sh", "sh", "-c", command, NULL);
        !           128:       _IO__exit(127);
        !           129:     }
        !           130:   _IO_close(child_end);
        !           131:   if (child_pid < 0)
        !           132:     {
        !           133:       _IO_close(parent_end);
        !           134:       return NULL;
        !           135:     }
        !           136:   _IO_fileno(fp) = parent_end;
        !           137: 
        !           138:   /* Link into proc_file_chain. */
        !           139:   ((_IO_proc_file*)fp)->_next = proc_file_chain;
        !           140:   proc_file_chain = (_IO_proc_file*)fp;
        !           141: 
        !           142:   fp->_IO_file_flags
        !           143:     = read_or_write | (fp->_IO_file_flags & ~(_IO_NO_READS|_IO_NO_WRITES));
        !           144:   return fp;
        !           145: #else /* !_IO_HAVE_SYS_WAIT */
        !           146:   return NULL;
        !           147: #endif
        !           148: }
        !           149: 
        !           150: _IO_FILE *
        !           151: _IO_popen(command, mode)
        !           152:      const char *command;
        !           153:      const char *mode;
        !           154: {
        !           155:   _IO_proc_file *fpx = (_IO_proc_file*)malloc(sizeof(_IO_proc_file));
        !           156:   _IO_FILE *fp = (_IO_FILE*)fpx;
        !           157:   if (fp == NULL)
        !           158:     return NULL;
        !           159:   _IO_init(fp, 0);
        !           160:   fp->_jumps = &_IO_proc_jumps;
        !           161:   _IO_file_init(fp);
        !           162:   ((struct _IO_FILE_plus*)fp)->_vtable = NULL;
        !           163:   if (_IO_proc_open (fp, command, mode) != NULL)
        !           164:     return fp;
        !           165:   free (fpx);
        !           166:   return NULL;
        !           167: }
        !           168: 
        !           169: int
        !           170: _IO_proc_close(fp)
        !           171:      _IO_FILE *fp;
        !           172: {
        !           173:   /* This is not name-space clean. FIXME! */
        !           174: #if _IO_HAVE_SYS_WAIT
        !           175:   int wstatus;
        !           176:   _IO_proc_file **ptr = &proc_file_chain;
        !           177:   _IO_pid_t wait_pid;
        !           178:   int status = _IO_close(_IO_fileno(fp));
        !           179: 
        !           180:   /* Unlink from proc_file_chain. */
        !           181:   for ( ; *ptr != NULL; ptr = &(*ptr)->_next)
        !           182:     {
        !           183:       if (*ptr == (_IO_proc_file*)fp)
        !           184:        {
        !           185:          *ptr = (*ptr)->_next;
        !           186:          break;
        !           187:        }
        !           188:     }
        !           189: 
        !           190:   if (status < 0)
        !           191:     return status;
        !           192:   /* POSIX.2 Rationale:  "Some historical implementations either block
        !           193:      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
        !           194:      for the child process to terminate.  Since this behavior is not
        !           195:      described in POSIX.2, such implementations are not conforming." */
        !           196:   do
        !           197:     {
        !           198:       wait_pid = _IO_waitpid (((_IO_proc_file*)fp)->_pid, &wstatus, 0);
        !           199:     } while (wait_pid == -1 && errno == EINTR);
        !           200:   if (wait_pid == -1)
        !           201:     return -1;
        !           202:   return wstatus;
        !           203: #else /* !_IO_HAVE_SYS_WAIT */
        !           204:   return -1;
        !           205: #endif
        !           206: }
        !           207: 
        !           208: struct _IO_jump_t _IO_proc_jumps = {
        !           209:   _IO_file_overflow,
        !           210:   _IO_file_underflow,
        !           211:   _IO_file_xsputn,
        !           212:   _IO_default_xsgetn,
        !           213:   _IO_file_read,
        !           214:   _IO_file_write,
        !           215:   _IO_file_doallocate,
        !           216:   _IO_default_pbackfail,
        !           217:   _IO_file_setbuf,
        !           218:   _IO_file_sync,
        !           219:   _IO_file_finish,
        !           220:   _IO_proc_close,
        !           221:   _IO_file_stat,
        !           222:   _IO_file_seek,
        !           223:   _IO_file_seekoff,
        !           224:   _IO_default_seekpos,
        !           225: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.