Back to index

glibc  2.9
iopopen.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993, 1997-2002, 2003, 2004, 2007, 2008
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Written by Per Bothner <bothner@cygnus.com>.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.
00020 
00021    As a special exception, if you link the code in this file with
00022    files compiled with a GNU compiler to produce an executable,
00023    that does not cause the resulting executable to be covered by
00024    the GNU Lesser General Public License.  This exception does not
00025    however invalidate any other reasons why the executable file
00026    might be covered by the GNU Lesser General Public License.
00027    This exception applies to code released by its copyright holders
00028    in files containing the exception.  */
00029 
00030 #ifndef _POSIX_SOURCE
00031 # define _POSIX_SOURCE
00032 #endif
00033 #include "libioP.h"
00034 #if _IO_HAVE_SYS_WAIT
00035 #include <signal.h>
00036 #include <unistd.h>
00037 #ifdef __STDC__
00038 #include <stdlib.h>
00039 #endif
00040 #ifdef _LIBC
00041 # include <unistd.h>
00042 # include <shlib-compat.h>
00043 # include <not-cancel.h>
00044 #endif
00045 #include <sys/types.h>
00046 #include <sys/wait.h>
00047 #include <kernel-features.h>
00048 
00049 #ifndef _IO_fork
00050 #ifdef _LIBC
00051 #define _IO_fork __fork
00052 #else
00053 #define _IO_fork fork /* defined in libiberty, if needed */
00054 #endif
00055 extern _IO_pid_t _IO_fork (void) __THROW;
00056 #endif
00057 
00058 #endif /* _IO_HAVE_SYS_WAIT */
00059 
00060 #ifndef _IO_dup2
00061 #ifdef _LIBC
00062 #define _IO_dup2 __dup2
00063 #else
00064 #define _IO_dup2 dup2
00065 #endif
00066 extern int _IO_dup2 (int fd, int fd2) __THROW;
00067 #endif
00068 
00069 #ifndef _IO_waitpid
00070 #ifdef _LIBC
00071 #define _IO_waitpid waitpid_not_cancel
00072 #else
00073 #define _IO_waitpid waitpid
00074 #endif
00075 #endif
00076 
00077 #ifndef _IO_execl
00078 #define _IO_execl execl
00079 #endif
00080 #ifndef _IO__exit
00081 #define _IO__exit _exit
00082 #endif
00083 
00084 #ifndef _IO_close
00085 #ifdef _LIBC
00086 #define _IO_close close_not_cancel
00087 #else
00088 #define _IO_close close
00089 #endif
00090 #endif
00091 
00092 struct _IO_proc_file
00093 {
00094   struct _IO_FILE_plus file;
00095   /* Following fields must match those in class procbuf (procbuf.h) */
00096   _IO_pid_t pid;
00097   struct _IO_proc_file *next;
00098 };
00099 typedef struct _IO_proc_file _IO_proc_file;
00100 
00101 static const struct _IO_jump_t _IO_proc_jumps;
00102 
00103 static struct _IO_proc_file *proc_file_chain;
00104 
00105 #ifdef _IO_MTSAFE_IO
00106 static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
00107 
00108 static void
00109 unlock (void *not_used)
00110 {
00111   _IO_lock_unlock (proc_file_chain_lock);
00112 }
00113 #endif
00114 
00115 _IO_FILE *
00116 _IO_new_proc_open (fp, command, mode)
00117      _IO_FILE *fp;
00118      const char *command;
00119      const char *mode;
00120 {
00121 #if _IO_HAVE_SYS_WAIT
00122   int read_or_write;
00123   int parent_end, child_end;
00124   int pipe_fds[2];
00125   _IO_pid_t child_pid;
00126 
00127   int do_read = 0;
00128   int do_write = 0;
00129   int do_cloexec = 0;
00130   while (*mode != '\0')
00131     switch (*mode++)
00132       {
00133       case 'r':
00134        do_read = 1;
00135        break;
00136       case 'w':
00137        do_write = 1;
00138        break;
00139       case 'e':
00140        do_cloexec = 1;
00141        break;
00142       default:
00143       errout:
00144        __set_errno (EINVAL);
00145        return NULL;
00146       }
00147 
00148   if ((do_read ^ do_write) == 0)
00149     goto errout;
00150 
00151   if (_IO_file_is_open (fp))
00152     return NULL;
00153 
00154 #ifdef O_CLOEXEC
00155 # ifndef __ASSUME_PIPE2
00156   if (__have_pipe2 >= 0)
00157 # endif
00158     {
00159       int r = __pipe2 (pipe_fds, O_CLOEXEC);
00160 # ifndef __ASSUME_PIPE2
00161       if (__have_pipe2 == 0)
00162        __have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;
00163 
00164       if (__have_pipe2 > 0)
00165 # endif
00166        if (r < 0)
00167          return NULL;
00168     }
00169 #endif
00170 #ifndef __ASSUME_PIPE2
00171 # ifdef O_CLOEXEC
00172   if (__have_pipe2 < 0)
00173 # endif
00174     if (__pipe (pipe_fds) < 0)
00175       return NULL;
00176 #endif
00177 
00178   if (do_read)
00179     {
00180       parent_end = pipe_fds[0];
00181       child_end = pipe_fds[1];
00182       read_or_write = _IO_NO_WRITES;
00183     }
00184   else
00185     {
00186       parent_end = pipe_fds[1];
00187       child_end = pipe_fds[0];
00188       read_or_write = _IO_NO_READS;
00189     }
00190 
00191   ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
00192   if (child_pid == 0)
00193     {
00194       int child_std_end = do_read ? 1 : 0;
00195       struct _IO_proc_file *p;
00196 
00197 #ifndef __ASSUME_PIPE2
00198       /* If we have pipe2 the descriptor is marked for close-on-exec.  */
00199       _IO_close (parent_end);
00200 #endif
00201       if (child_end != child_std_end)
00202        {
00203          _IO_dup2 (child_end, child_std_end);
00204 #ifndef __ASSUME_PIPE2
00205          _IO_close (child_end);
00206 #endif
00207        }
00208 #ifdef O_CLOEXEC
00209       else
00210        {
00211          /* The descriptor is already the one we will use.  But it must
00212             not be marked close-on-exec.  Undo the effects.  */
00213 # ifndef __ASSUME_PIPE2
00214          if (__have_pipe2 > 0)
00215 # endif
00216            __fcntl (child_end, F_SETFD, 0);
00217        }
00218 #endif
00219       /* POSIX.2:  "popen() shall ensure that any streams from previous
00220          popen() calls that remain open in the parent process are closed
00221         in the new child process." */
00222       for (p = proc_file_chain; p; p = p->next)
00223        {
00224          int fd = _IO_fileno ((_IO_FILE *) p);
00225 
00226          /* If any stream from previous popen() calls has fileno
00227             child_std_end, it has been already closed by the dup2 syscall
00228             above.  */
00229          if (fd != child_std_end)
00230            _IO_close (fd);
00231        }
00232 
00233       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
00234       _IO__exit (127);
00235     }
00236   _IO_close (child_end);
00237   if (child_pid < 0)
00238     {
00239       _IO_close (parent_end);
00240       return NULL;
00241     }
00242 
00243   if (do_cloexec)
00244     {
00245 #ifndef __ASSUME_PIPE2
00246 # ifdef O_CLOEXEC
00247       if (__have_pipe2 < 0)
00248 # endif
00249        __fcntl (parent_end, F_SETFD, FD_CLOEXEC);
00250 #endif
00251     }
00252   else
00253     {
00254 #ifdef O_CLOEXEC
00255       /* Undo the effects of the pipe2 call which set the
00256         close-on-exec flag.  */
00257 # ifndef __ASSUME_PIPE2
00258       if (__have_pipe2 > 0)
00259 # endif
00260        __fcntl (parent_end, F_SETFD, 0);
00261 #endif
00262     }
00263 
00264   _IO_fileno (fp) = parent_end;
00265 
00266   /* Link into proc_file_chain. */
00267 #ifdef _IO_MTSAFE_IO
00268   _IO_cleanup_region_start_noarg (unlock);
00269   _IO_lock_lock (proc_file_chain_lock);
00270 #endif
00271   ((_IO_proc_file *) fp)->next = proc_file_chain;
00272   proc_file_chain = (_IO_proc_file *) fp;
00273 #ifdef _IO_MTSAFE_IO
00274   _IO_lock_unlock (proc_file_chain_lock);
00275   _IO_cleanup_region_end (0);
00276 #endif
00277 
00278   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
00279   return fp;
00280 #else /* !_IO_HAVE_SYS_WAIT */
00281   return NULL;
00282 #endif
00283 }
00284 
00285 _IO_FILE *
00286 _IO_new_popen (command, mode)
00287      const char *command;
00288      const char *mode;
00289 {
00290   struct locked_FILE
00291   {
00292     struct _IO_proc_file fpx;
00293 #ifdef _IO_MTSAFE_IO
00294     _IO_lock_t lock;
00295 #endif
00296   } *new_f;
00297   _IO_FILE *fp;
00298 
00299   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
00300   if (new_f == NULL)
00301     return NULL;
00302 #ifdef _IO_MTSAFE_IO
00303   new_f->fpx.file.file._lock = &new_f->lock;
00304 #endif
00305   fp = &new_f->fpx.file.file;
00306   INTUSE(_IO_init) (fp, 0);
00307   _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
00308   _IO_new_file_init (&new_f->fpx.file);
00309 #if  !_IO_UNIFIED_JUMPTABLES
00310   new_f->fpx.file.vtable = NULL;
00311 #endif
00312   if (_IO_new_proc_open (fp, command, mode) != NULL)
00313     return (_IO_FILE *) &new_f->fpx.file;
00314   INTUSE(_IO_un_link) (&new_f->fpx.file);
00315   free (new_f);
00316   return NULL;
00317 }
00318 
00319 int
00320 _IO_new_proc_close (fp)
00321      _IO_FILE *fp;
00322 {
00323   /* This is not name-space clean. FIXME! */
00324 #if _IO_HAVE_SYS_WAIT
00325   int wstatus;
00326   _IO_proc_file **ptr = &proc_file_chain;
00327   _IO_pid_t wait_pid;
00328   int status = -1;
00329 
00330   /* Unlink from proc_file_chain. */
00331 #ifdef _IO_MTSAFE_IO
00332   _IO_cleanup_region_start_noarg (unlock);
00333   _IO_lock_lock (proc_file_chain_lock);
00334 #endif
00335   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
00336     {
00337       if (*ptr == (_IO_proc_file *) fp)
00338        {
00339          *ptr = (*ptr)->next;
00340          status = 0;
00341          break;
00342        }
00343     }
00344 #ifdef _IO_MTSAFE_IO
00345   _IO_lock_unlock (proc_file_chain_lock);
00346   _IO_cleanup_region_end (0);
00347 #endif
00348 
00349   if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
00350     return -1;
00351   /* POSIX.2 Rationale:  "Some historical implementations either block
00352      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
00353      for the child process to terminate.  Since this behavior is not
00354      described in POSIX.2, such implementations are not conforming." */
00355   do
00356     {
00357       wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
00358     }
00359   while (wait_pid == -1 && errno == EINTR);
00360   if (wait_pid == -1)
00361     return -1;
00362   return wstatus;
00363 #else /* !_IO_HAVE_SYS_WAIT */
00364   return -1;
00365 #endif
00366 }
00367 
00368 static const struct _IO_jump_t _IO_proc_jumps = {
00369   JUMP_INIT_DUMMY,
00370   JUMP_INIT(finish, _IO_new_file_finish),
00371   JUMP_INIT(overflow, _IO_new_file_overflow),
00372   JUMP_INIT(underflow, _IO_new_file_underflow),
00373   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
00374   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
00375   JUMP_INIT(xsputn, _IO_new_file_xsputn),
00376   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
00377   JUMP_INIT(seekoff, _IO_new_file_seekoff),
00378   JUMP_INIT(seekpos, _IO_default_seekpos),
00379   JUMP_INIT(setbuf, _IO_new_file_setbuf),
00380   JUMP_INIT(sync, _IO_new_file_sync),
00381   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
00382   JUMP_INIT(read, INTUSE(_IO_file_read)),
00383   JUMP_INIT(write, _IO_new_file_write),
00384   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
00385   JUMP_INIT(close, _IO_new_proc_close),
00386   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
00387   JUMP_INIT(showmanyc, _IO_default_showmanyc),
00388   JUMP_INIT(imbue, _IO_default_imbue)
00389 };
00390 
00391 strong_alias (_IO_new_popen, __new_popen)
00392 versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
00393 versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
00394 versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
00395 versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);