Back to index

glibc  2.9
oldiopopen.c
Go to the documentation of this file.
00001 /* Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Written by Per Bothner <bothner@cygnus.com>.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.
00019 
00020    As a special exception, if you link the code in this file with
00021    files compiled with a GNU compiler to produce an executable,
00022    that does not cause the resulting executable to be covered by
00023    the GNU Lesser General Public License.  This exception does not
00024    however invalidate any other reasons why the executable file
00025    might be covered by the GNU Lesser General Public License.
00026    This exception applies to code released by its copyright holders
00027    in files containing the exception.  */
00028 
00029 #define _IO_USE_OLD_IO_FILE
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 #endif
00043 #include <sys/types.h>
00044 #include <sys/wait.h>
00045 
00046 #ifndef _IO_fork
00047 #ifdef _LIBC
00048 #define _IO_fork __fork
00049 #else
00050 #define _IO_fork fork /* defined in libiberty, if needed */
00051 #endif
00052 extern _IO_pid_t _IO_fork (void) __THROW;
00053 #endif
00054 
00055 #endif /* _IO_HAVE_SYS_WAIT */
00056 
00057 #include <shlib-compat.h>
00058 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
00059 
00060 #ifndef _IO_pipe
00061 #ifdef _LIBC
00062 #define _IO_pipe __pipe
00063 #else
00064 #define _IO_pipe pipe
00065 #endif
00066 extern int _IO_pipe (int des[2]) __THROW;
00067 #endif
00068 
00069 #ifndef _IO_dup2
00070 #ifdef _LIBC
00071 #define _IO_dup2 __dup2
00072 #else
00073 #define _IO_dup2 dup2
00074 #endif
00075 extern int _IO_dup2 (int fd, int fd2) __THROW;
00076 #endif
00077 
00078 #ifndef _IO_waitpid
00079 #ifdef _LIBC
00080 #define _IO_waitpid __waitpid
00081 #else
00082 #define _IO_waitpid waitpid
00083 #endif
00084 #endif
00085 
00086 #ifndef _IO_execl
00087 #define _IO_execl execl
00088 #endif
00089 #ifndef _IO__exit
00090 #define _IO__exit _exit
00091 #endif
00092 
00093 #ifndef _IO_close
00094 #ifdef _LIBC
00095 #define _IO_close __close
00096 #else
00097 #define _IO_close close
00098 #endif
00099 #endif
00100 
00101 struct _IO_proc_file
00102 {
00103   struct _IO_FILE_complete_plus file;
00104   /* Following fields must match those in class procbuf (procbuf.h) */
00105   _IO_pid_t pid;
00106   struct _IO_proc_file *next;
00107 };
00108 typedef struct _IO_proc_file _IO_proc_file;
00109 
00110 static struct _IO_proc_file *old_proc_file_chain;
00111 
00112 #ifdef _IO_MTSAFE_IO
00113 static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
00114 
00115 static void
00116 unlock (void *not_used)
00117 {
00118   _IO_lock_unlock (proc_file_chain_lock);
00119 }
00120 #endif
00121 
00122 _IO_FILE *
00123 attribute_compat_text_section
00124 _IO_old_proc_open (fp, command, mode)
00125      _IO_FILE *fp;
00126      const char *command;
00127      const char *mode;
00128 {
00129 #if _IO_HAVE_SYS_WAIT
00130   volatile int read_or_write;
00131   volatile int parent_end, child_end;
00132   int pipe_fds[2];
00133   _IO_pid_t child_pid;
00134   if (_IO_file_is_open (fp))
00135     return NULL;
00136   if (_IO_pipe (pipe_fds) < 0)
00137     return NULL;
00138   if (mode[0] == 'r' && mode[1] == '\0')
00139     {
00140       parent_end = pipe_fds[0];
00141       child_end = pipe_fds[1];
00142       read_or_write = _IO_NO_WRITES;
00143     }
00144   else if (mode[0] == 'w' && mode[1] == '\0')
00145     {
00146       parent_end = pipe_fds[1];
00147       child_end = pipe_fds[0];
00148       read_or_write = _IO_NO_READS;
00149     }
00150   else
00151     {
00152       _IO_close (pipe_fds[0]);
00153       _IO_close (pipe_fds[1]);
00154       __set_errno (EINVAL);
00155       return NULL;
00156     }
00157   ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
00158   if (child_pid == 0)
00159     {
00160       int child_std_end = mode[0] == 'r' ? 1 : 0;
00161       struct _IO_proc_file *p;
00162 
00163       _IO_close (parent_end);
00164       if (child_end != child_std_end)
00165        {
00166          _IO_dup2 (child_end, child_std_end);
00167          _IO_close (child_end);
00168        }
00169       /* POSIX.2:  "popen() shall ensure that any streams from previous
00170          popen() calls that remain open in the parent process are closed
00171         in the new child process." */
00172       for (p = old_proc_file_chain; p; p = p->next)
00173        _IO_close (_IO_fileno ((_IO_FILE *) p));
00174 
00175       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
00176       _IO__exit (127);
00177     }
00178   _IO_close (child_end);
00179   if (child_pid < 0)
00180     {
00181       _IO_close (parent_end);
00182       return NULL;
00183     }
00184   _IO_fileno (fp) = parent_end;
00185 
00186   /* Link into old_proc_file_chain. */
00187 #ifdef _IO_MTSAFE_IO
00188   _IO_cleanup_region_start_noarg (unlock);
00189   _IO_lock_lock (proc_file_chain_lock);
00190 #endif
00191   ((_IO_proc_file *) fp)->next = old_proc_file_chain;
00192   old_proc_file_chain = (_IO_proc_file *) fp;
00193 #ifdef _IO_MTSAFE_IO
00194   _IO_lock_unlock (proc_file_chain_lock);
00195   _IO_cleanup_region_end (0);
00196 #endif
00197 
00198   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
00199   return fp;
00200 #else /* !_IO_HAVE_SYS_WAIT */
00201   return NULL;
00202 #endif
00203 }
00204 
00205 _IO_FILE *
00206 attribute_compat_text_section
00207 _IO_old_popen (command, mode)
00208      const char *command;
00209      const char *mode;
00210 {
00211   struct locked_FILE
00212   {
00213     struct _IO_proc_file fpx;
00214 #ifdef _IO_MTSAFE_IO
00215     _IO_lock_t lock;
00216 #endif
00217   } *new_f;
00218   _IO_FILE *fp;
00219 
00220   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
00221   if (new_f == NULL)
00222     return NULL;
00223 #ifdef _IO_MTSAFE_IO
00224   new_f->fpx.file.file._file._lock = &new_f->lock;
00225 #endif
00226   fp = &new_f->fpx.file.file._file;
00227   _IO_old_init (fp, 0);
00228   _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fpx.file) = &_IO_old_proc_jumps;
00229   _IO_old_file_init ((struct _IO_FILE_plus *) &new_f->fpx.file);
00230 #if  !_IO_UNIFIED_JUMPTABLES
00231   new_f->fpx.file.vtable = NULL;
00232 #endif
00233   if (_IO_old_proc_open (fp, command, mode) != NULL)
00234     return fp;
00235   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) &new_f->fpx.file);
00236   free (new_f);
00237   return NULL;
00238 }
00239 
00240 int
00241 attribute_compat_text_section
00242 _IO_old_proc_close (fp)
00243      _IO_FILE *fp;
00244 {
00245   /* This is not name-space clean. FIXME! */
00246 #if _IO_HAVE_SYS_WAIT
00247   int wstatus;
00248   _IO_proc_file **ptr = &old_proc_file_chain;
00249   _IO_pid_t wait_pid;
00250   int status = -1;
00251 
00252   /* Unlink from old_proc_file_chain. */
00253 #ifdef _IO_MTSAFE_IO
00254   _IO_cleanup_region_start_noarg (unlock);
00255   _IO_lock_lock (proc_file_chain_lock);
00256 #endif
00257   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
00258     {
00259       if (*ptr == (_IO_proc_file *) fp)
00260        {
00261          *ptr = (*ptr)->next;
00262          status = 0;
00263          break;
00264        }
00265     }
00266 #ifdef _IO_MTSAFE_IO
00267   _IO_lock_unlock (proc_file_chain_lock);
00268   _IO_cleanup_region_end (0);
00269 #endif
00270 
00271   if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
00272     return -1;
00273   /* POSIX.2 Rationale:  "Some historical implementations either block
00274      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
00275      for the child process to terminate.  Since this behavior is not
00276      described in POSIX.2, such implementations are not conforming." */
00277   do
00278     {
00279       wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
00280     }
00281   while (wait_pid == -1 && errno == EINTR);
00282   if (wait_pid == -1)
00283     return -1;
00284   return wstatus;
00285 #else /* !_IO_HAVE_SYS_WAIT */
00286   return -1;
00287 #endif
00288 }
00289 
00290 const struct _IO_jump_t _IO_old_proc_jumps = {
00291   JUMP_INIT_DUMMY,
00292   JUMP_INIT(finish, _IO_old_file_finish),
00293   JUMP_INIT(overflow, _IO_old_file_overflow),
00294   JUMP_INIT(underflow, _IO_old_file_underflow),
00295   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
00296   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
00297   JUMP_INIT(xsputn, _IO_old_file_xsputn),
00298   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
00299   JUMP_INIT(seekoff, _IO_old_file_seekoff),
00300   JUMP_INIT(seekpos, _IO_default_seekpos),
00301   JUMP_INIT(setbuf, _IO_old_file_setbuf),
00302   JUMP_INIT(sync, _IO_old_file_sync),
00303   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
00304   JUMP_INIT(read, INTUSE(_IO_file_read)),
00305   JUMP_INIT(write, _IO_old_file_write),
00306   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
00307   JUMP_INIT(close, _IO_old_proc_close),
00308   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
00309   JUMP_INIT(showmanyc, _IO_default_showmanyc),
00310   JUMP_INIT(imbue, _IO_default_imbue)
00311 };
00312 
00313 strong_alias (_IO_old_popen, __old_popen)
00314 compat_symbol (libc, _IO_old_popen, _IO_popen, GLIBC_2_0);
00315 compat_symbol (libc, __old_popen, popen, GLIBC_2_0);
00316 compat_symbol (libc, _IO_old_proc_open, _IO_proc_open, GLIBC_2_0);
00317 compat_symbol (libc, _IO_old_proc_close, _IO_proc_close, GLIBC_2_0);
00318 
00319 #endif