(linenum→info "unix/slp.c:2238")

glibc/2.7/libio/iopopen.c

    1: /* Copyright (C) 1993, 1997-2002, 2003, 2004, 2007
    2:    Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:    Written by Per Bothner <bothner@cygnus.com>.
    5: 
    6:    The GNU C Library is free software; you can redistribute it and/or
    7:    modify it under the terms of the GNU Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the License, or (at your option) any later version.
   10: 
   11:    The GNU C Library is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.
   20: 
   21:    As a special exception, if you link the code in this file with
   22:    files compiled with a GNU compiler to produce an executable,
   23:    that does not cause the resulting executable to be covered by
   24:    the GNU Lesser General Public License.  This exception does not
   25:    however invalidate any other reasons why the executable file
   26:    might be covered by the GNU Lesser General Public License.
   27:    This exception applies to code released by its copyright holders
   28:    in files containing the exception.  */
   29: 
   30: #ifndef _POSIX_SOURCE
   31: # define _POSIX_SOURCE
   32: #endif
   33: #include "libioP.h"
   34: #if _IO_HAVE_SYS_WAIT
   35: #include <signal.h>
   36: #include <unistd.h>
   37: #ifdef __STDC__
   38: #include <stdlib.h>
   39: #endif
   40: #ifdef _LIBC
   41: # include <unistd.h>
   42: # include <shlib-compat.h>
   43: # include <not-cancel.h>
   44: #endif
   45: #include <sys/types.h>
   46: #include <sys/wait.h>
   47: 
   48: #ifndef _IO_fork
   49: #ifdef _LIBC
   50: #define _IO_fork __fork
   51: #else
   52: #define _IO_fork fork /* defined in libiberty, if needed */
   53: #endif
   54: extern _IO_pid_t _IO_fork (void) __THROW;
   55: #endif
   56: 
   57: #endif /* _IO_HAVE_SYS_WAIT */
   58: 
   59: #ifndef _IO_pipe
   60: #ifdef _LIBC
   61: #define _IO_pipe __pipe
   62: #else
   63: #define _IO_pipe pipe
   64: #endif
   65: extern int _IO_pipe (int des[2]) __THROW;
   66: #endif
   67: 
   68: #ifndef _IO_dup2
   69: #ifdef _LIBC
   70: #define _IO_dup2 __dup2
   71: #else
   72: #define _IO_dup2 dup2
   73: #endif
   74: extern int _IO_dup2 (int fd, int fd2) __THROW;
   75: #endif
   76: 
   77: #ifndef _IO_waitpid
   78: #ifdef _LIBC
   79: #define _IO_waitpid waitpid_not_cancel
   80: #else
   81: #define _IO_waitpid waitpid
   82: #endif
   83: #endif
   84: 
   85: #ifndef _IO_execl
   86: #define _IO_execl execl
   87: #endif
   88: #ifndef _IO__exit
   89: #define _IO__exit _exit
   90: #endif
   91: 
   92: #ifndef _IO_close
   93: #ifdef _LIBC
   94: #define _IO_close close_not_cancel
   95: #else
   96: #define _IO_close close
   97: #endif
   98: #endif
   99: 
  100: struct _IO_proc_file
  101: {
  102:   struct _IO_FILE_plus file;
  103:   /* Following fields must match those in class procbuf (procbuf.h) */
  104:   _IO_pid_t pid;
  105:   struct _IO_proc_file *next;
  106: };
  107: typedef struct _IO_proc_file _IO_proc_file;
  108: 
  109: static const struct _IO_jump_t _IO_proc_jumps;
  110: 
  111: static struct _IO_proc_file *proc_file_chain;
  112: 
  113: #ifdef _IO_MTSAFE_IO
  114: static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
  115: 
  116: static void
  117: unlock (void *not_used)
  118: {
  119:   _IO_lock_unlock (proc_file_chain_lock);
  120: }
  121: #endif
  122: 
  123: _IO_FILE *
  124: _IO_new_proc_open (fp, command, mode)
  125:      _IO_FILE *fp;
  126:      const char *command;
  127:      const char *mode;
  128: {
  129: #if _IO_HAVE_SYS_WAIT
  130:   volatile int read_or_write;
  131:   volatile int parent_end, child_end;
  132:   int pipe_fds[2];
  133:   _IO_pid_t child_pid;
  134:   if (_IO_file_is_open (fp))
  135:     return NULL;
  136:   if (_IO_pipe (pipe_fds) < 0)
  137:     return NULL;
  138:   if (mode[0] == 'r' && mode[1] == '\0')
  139:     {
  140:       parent_end = pipe_fds[0];
  141:       child_end = pipe_fds[1];
  142:       read_or_write = _IO_NO_WRITES;
  143:     }
  144:   else if (mode[0] == 'w' && mode[1] == '\0')
  145:     {
  146:       parent_end = pipe_fds[1];
  147:       child_end = pipe_fds[0];
  148:       read_or_write = _IO_NO_READS;
  149:     }
  150:   else
  151:     {
  152:       _IO_close (pipe_fds[0]);
  153:       _IO_close (pipe_fds[1]);
  154:       __set_errno (EINVAL);
  155:       return NULL;
  156:     }
  157:   ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
  158:   if (child_pid == 0)
  159:     {
  160:       int child_std_end = mode[0] == 'r' ? 1 : 0;
  161:       struct _IO_proc_file *p;
  162: 
  163:       _IO_close (parent_end);
  164:       if (child_end != child_std_end)
  165:         {
  166:           _IO_dup2 (child_end, child_std_end);
  167:           _IO_close (child_end);
  168:         }
  169:       /* POSIX.2:  "popen() shall ensure that any streams from previous
  170:          popen() calls that remain open in the parent process are closed
  171:          in the new child process." */
  172:       for (p = proc_file_chain; p; p = p->next)
  173:         {
  174:           int fd = _IO_fileno ((_IO_FILE *) p);
  175: 
  176:           /* If any stream from previous popen() calls has fileno
  177:              child_std_end, it has been already closed by the dup2 syscall
  178:              above.  */
  179:           if (fd != child_std_end)
  180:             _IO_close (fd);
  181:         }
  182: 
  183:       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
  184:       _IO__exit (127);
  185:     }
  186:   _IO_close (child_end);
  187:   if (child_pid < 0)
  188:     {
  189:       _IO_close (parent_end);
  190:       return NULL;
  191:     }
  192:   _IO_fileno (fp) = parent_end;
  193: 
  194:   /* Link into proc_file_chain. */
  195: #ifdef _IO_MTSAFE_IO
  196:   _IO_cleanup_region_start_noarg (unlock);
  197:   _IO_lock_lock (proc_file_chain_lock);
  198: #endif
  199:   ((_IO_proc_file *) fp)->next = proc_file_chain;
  200:   proc_file_chain = (_IO_proc_file *) fp;
  201: #ifdef _IO_MTSAFE_IO
  202:   _IO_lock_unlock (proc_file_chain_lock);
  203:   _IO_cleanup_region_end (0);
  204: #endif
  205: 
  206:   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
  207:   return fp;
  208: #else /* !_IO_HAVE_SYS_WAIT */
  209:   return NULL;
  210: #endif
  211: }
  212: 
  213: _IO_FILE *
  214: _IO_new_popen (command, mode)
  215:      const char *command;
  216:      const char *mode;
  217: {
  218:   struct locked_FILE
  219:   {
  220:     struct _IO_proc_file fpx;
  221: #ifdef _IO_MTSAFE_IO
  222:     _IO_lock_t lock;
  223: #endif
  224:   } *new_f;
  225:   _IO_FILE *fp;
  226: 
  227:   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
  228:   if (new_f == NULL)
  229:     return NULL;
  230: #ifdef _IO_MTSAFE_IO
  231:   new_f->fpx.file.file._lock = &new_f->lock;
  232: #endif
  233:   fp = &new_f->fpx.file.file;
  234:   INTUSE(_IO_init) (fp, 0);
  235:   _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
  236:   _IO_new_file_init (&new_f->fpx.file);
  237: #if  !_IO_UNIFIED_JUMPTABLES
  238:   new_f->fpx.file.vtable = NULL;
  239: #endif
  240:   if (_IO_new_proc_open (fp, command, mode) != NULL)
  241:     return (_IO_FILE *) &new_f->fpx.file;
  242:   INTUSE(_IO_un_link) (&new_f->fpx.file);
  243:   free (new_f);
  244:   return NULL;
  245: }
  246: 
  247: int
  248: _IO_new_proc_close (fp)
  249:      _IO_FILE *fp;
  250: {
  251:   /* This is not name-space clean. FIXME! */
  252: #if _IO_HAVE_SYS_WAIT
  253:   int wstatus;
  254:   _IO_proc_file **ptr = &proc_file_chain;
  255:   _IO_pid_t wait_pid;
  256:   int status = -1;
  257: 
  258:   /* Unlink from proc_file_chain. */
  259: #ifdef _IO_MTSAFE_IO
  260:   _IO_cleanup_region_start_noarg (unlock);
  261:   _IO_lock_lock (proc_file_chain_lock);
  262: #endif
  263:   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
  264:     {
  265:       if (*ptr == (_IO_proc_file *) fp)
  266:         {
  267:           *ptr = (*ptr)->next;
  268:           status = 0;
  269:           break;
  270:         }
  271:     }
  272: #ifdef _IO_MTSAFE_IO
  273:   _IO_lock_unlock (proc_file_chain_lock);
  274:   _IO_cleanup_region_end (0);
  275: #endif
  276: 
  277:   if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
  278:     return -1;
  279:   /* POSIX.2 Rationale:  "Some historical implementations either block
  280:      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
  281:      for the child process to terminate.  Since this behavior is not
  282:      described in POSIX.2, such implementations are not conforming." */
  283:   do
  284:     {
  285:       wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
  286:     }
  287:   while (wait_pid == -1 && errno == EINTR);
  288:   if (wait_pid == -1)
  289:     return -1;
  290:   return wstatus;
  291: #else /* !_IO_HAVE_SYS_WAIT */
  292:   return -1;
  293: #endif
  294: }
  295: 
  296: static const struct _IO_jump_t _IO_proc_jumps = {
  297:   JUMP_INIT_DUMMY,
  298:   JUMP_INIT(finish, _IO_new_file_finish),
  299:   JUMP_INIT(overflow, _IO_new_file_overflow),
  300:   JUMP_INIT(underflow, _IO_new_file_underflow),
  301:   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
  302:   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
  303:   JUMP_INIT(xsputn, _IO_new_file_xsputn),
  304:   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
  305:   JUMP_INIT(seekoff, _IO_new_file_seekoff),
  306:   JUMP_INIT(seekpos, _IO_default_seekpos),
  307:   JUMP_INIT(setbuf, _IO_new_file_setbuf),
  308:   JUMP_INIT(sync, _IO_new_file_sync),
  309:   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
  310:   JUMP_INIT(read, INTUSE(_IO_file_read)),
  311:   JUMP_INIT(write, _IO_new_file_write),
  312:   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
  313:   JUMP_INIT(close, _IO_new_proc_close),
  314:   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
  315:   JUMP_INIT(showmanyc, _IO_default_showmanyc),
  316:   JUMP_INIT(imbue, _IO_default_imbue)
  317: };
  318: 
  319: strong_alias (_IO_new_popen, __new_popen)
  320: versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
  321: versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
  322: versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
  323: versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);
Syntax (Markdown)