home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / libg++-2.7.1-base.tgz / libg++-2.7.1-src.tar / fsf / libg++ / libio / iopopen.c < prev    next >
C/C++ Source or Header  |  1995-09-11  |  6KB  |  223 lines

  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 this library; see the file COPYING.  If not, write to the Free
  17. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 (bothner@cygnus.com) */
  26.  
  27. #define _POSIX_SOURCE
  28. #include "libioP.h"
  29. #if _IO_HAVE_SYS_WAIT
  30. #include <signal.h>
  31. #include <unistd.h>
  32. #ifdef __STDC__
  33. #include <stdlib.h>
  34. #endif
  35. #include <sys/types.h>
  36. #include <sys/wait.h>
  37.  
  38. #ifndef _IO_fork
  39. #define _IO_fork vfork /* defined in libiberty, if needed */
  40. _IO_pid_t _IO_fork();
  41. #endif
  42.  
  43. #endif /* _IO_HAVE_SYS_WAIT */
  44.  
  45. #ifndef _IO_pipe
  46. #define _IO_pipe pipe
  47. extern int _IO_pipe();
  48. #endif
  49.  
  50. #ifndef _IO_dup2
  51. #define _IO_dup2 dup2
  52. extern int _IO_dup2();
  53. #endif
  54.  
  55. #ifndef _IO_waitpid
  56. #define _IO_waitpid waitpid
  57. #endif
  58.  
  59. #ifndef _IO_execl
  60. #define _IO_execl execl
  61. #endif
  62. #ifndef _IO__exit
  63. #define _IO__exit _exit
  64. #endif
  65.  
  66. struct _IO_proc_file
  67. {
  68.   struct _IO_FILE_plus file;
  69.   /* Following fields must match those in class procbuf (procbuf.h) */
  70.   _IO_pid_t pid;
  71.   struct _IO_proc_file *next;
  72. };
  73. typedef struct _IO_proc_file _IO_proc_file;
  74.  
  75. static struct _IO_proc_file *proc_file_chain = NULL;
  76.  
  77. _IO_FILE *
  78. DEFUN(_IO_proc_open, (fp, command, mode),
  79.       _IO_FILE* fp AND const char *command AND const char *mode)
  80. {
  81. #if _IO_HAVE_SYS_WAIT
  82.   int read_or_write;
  83.   int pipe_fds[2];
  84.   int parent_end, child_end;
  85.   _IO_pid_t child_pid;
  86.   if (_IO_file_is_open(fp))
  87.     return NULL;
  88.   if (_IO_pipe(pipe_fds) < 0)
  89.     return NULL;
  90.   if (mode[0] == 'r')
  91.     {
  92.       parent_end = pipe_fds[0];
  93.       child_end = pipe_fds[1];
  94.       read_or_write = _IO_NO_WRITES;
  95.     }
  96.   else
  97.     {
  98.       parent_end = pipe_fds[1];
  99.       child_end = pipe_fds[0];
  100.       read_or_write = _IO_NO_READS;
  101.     }
  102.   ((_IO_proc_file*)fp)->pid = child_pid = _IO_fork();
  103.   if (child_pid == 0)
  104.     {
  105.       int child_std_end = mode[0] == 'r' ? 1 : 0;
  106.       _IO_close(parent_end);
  107.       if (child_end != child_std_end)
  108.     {
  109.       _IO_dup2(child_end, child_std_end);
  110.       _IO_close(child_end);
  111.     }
  112.       /* Posix.2:  "popen() shall ensure that any streams from previous
  113.          popen() calls that remain open in the parent process are closed
  114.      in the new child process." */
  115.       while (proc_file_chain)
  116.     {
  117.       _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain));
  118.       proc_file_chain = proc_file_chain->next;
  119.     }
  120.  
  121.       _IO_execl("/bin/sh", "sh", "-c", command, NULL);
  122.       _IO__exit(127);
  123.     }
  124.   _IO_close(child_end);
  125.   if (child_pid < 0)
  126.     {
  127.       _IO_close(parent_end);
  128.       return NULL;
  129.     }
  130.   _IO_fileno(fp) = parent_end;
  131.  
  132.   /* Link into proc_file_chain. */
  133.   ((_IO_proc_file*)fp)->next = proc_file_chain;
  134.   proc_file_chain = (_IO_proc_file*)fp;
  135.  
  136.   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
  137.   return fp;
  138. #else /* !_IO_HAVE_SYS_WAIT */
  139.   return NULL;
  140. #endif
  141. }
  142.  
  143. _IO_FILE *
  144. DEFUN(_IO_popen, (command, mode),
  145.       const char *command AND const char *mode)
  146. {
  147.   _IO_proc_file *fpx = (_IO_proc_file*)malloc(sizeof(_IO_proc_file));
  148.   _IO_FILE *fp = (_IO_FILE*)fpx;
  149.   if (fp == NULL)
  150.     return NULL;
  151.   _IO_init(fp, 0);
  152.   _IO_JUMPS(fp) = &_IO_proc_jumps;
  153.   _IO_file_init(fp);
  154. #if  !_IO_UNIFIED_JUMPTABLES
  155.   ((struct _IO_FILE_plus*)fp)->vtable = NULL;
  156. #endif
  157.   if (_IO_proc_open (fp, command, mode) != NULL)
  158.     return fp;
  159.   free (fpx);
  160.   return NULL;
  161. }
  162.  
  163. int
  164. DEFUN(_IO_proc_close, (fp),
  165.       _IO_FILE *fp)
  166. {
  167.   /* This is not name-space clean. FIXME! */
  168. #if _IO_HAVE_SYS_WAIT
  169.   int wstatus;
  170.   _IO_proc_file **ptr = &proc_file_chain;
  171.   _IO_pid_t wait_pid;
  172.   int status = -1;
  173.   
  174.   /* Unlink from proc_file_chain. */
  175.   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
  176.     {
  177.       if (*ptr == (_IO_proc_file*)fp)
  178.     {
  179.       *ptr = (*ptr)->next;
  180.       status = 0;
  181.       break;
  182.     }
  183.     }
  184.  
  185.   if (status < 0 || _IO_close(_IO_fileno(fp)) < 0)
  186.     return -1;
  187.   /* POSIX.2 Rationale:  "Some historical implementations either block
  188.      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
  189.      for the child process to terminate.  Since this behavior is not
  190.      described in POSIX.2, such implementations are not conforming." */
  191.   do
  192.     {
  193.       wait_pid = _IO_waitpid (((_IO_proc_file*)fp)->pid, &wstatus, 0);
  194.     } while (wait_pid == -1 && errno == EINTR);
  195.   if (wait_pid == -1)
  196.     return -1;
  197.   return wstatus;
  198. #else /* !_IO_HAVE_SYS_WAIT */
  199.   return -1;
  200. #endif
  201. }
  202.  
  203. struct _IO_jump_t _IO_proc_jumps = {
  204.   JUMP_INIT_DUMMY,
  205.   JUMP_INIT(finish, _IO_file_finish),
  206.   JUMP_INIT(overflow, _IO_file_overflow),
  207.   JUMP_INIT(underflow, _IO_file_underflow),
  208.   JUMP_INIT(uflow, _IO_default_uflow),
  209.   JUMP_INIT(pbackfail, _IO_default_pbackfail),
  210.   JUMP_INIT(xsputn, _IO_file_xsputn),
  211.   JUMP_INIT(xsgetn, _IO_default_xsgetn),
  212.   JUMP_INIT(seekoff, _IO_file_seekoff),
  213.   JUMP_INIT(seekpos, _IO_default_seekpos),
  214.   JUMP_INIT(setbuf, _IO_file_setbuf),
  215.   JUMP_INIT(sync, _IO_file_sync),
  216.   JUMP_INIT(doallocate, _IO_file_doallocate),
  217.   JUMP_INIT(read, _IO_file_read),
  218.   JUMP_INIT(write, _IO_file_write),
  219.   JUMP_INIT(seek, _IO_file_seek),
  220.   JUMP_INIT(close, _IO_proc_close),
  221.   JUMP_INIT(stat, _IO_file_stat)
  222. };
  223.