Annotation of GNUtools/libg++/libio/iopopen.c, revision 1.1.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.