[Python-checkins] CVS: python/dist/src/Lib popen2.py,1.15,1.16

Fred L. Drake python-dev@python.org
Thu, 28 Sep 2000 12:07:57 -0700


Update of /cvsroot/python/python/dist/src/Lib
In directory slayer.i.sourceforge.net:/tmp/cvs-serv17798

Modified Files:
	popen2.py 
Log Message:

popen4(), class Popen4:  popen4() support for Unix.

popen2(), popen3():  Reversed order of bufsize and mode parameters to
                     comply with what was here before (Python 1.5.2).

class Popen3:  Factored the __init__() into a more basic initializer and
               a helper method, to allow some re-use by the Popen4 class.
               Use os.dup2() instead of os.dup() to create the proper
               file descriptors in the child process.

This closes SourceForge bug #115330 and partially closes #115353.


Index: popen2.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/popen2.py,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -r1.15 -r1.16
*** popen2.py	2000/09/01 20:38:54	1.15
--- popen2.py	2000/09/28 19:07:53	1.16
***************
*** 9,13 ****
  import os
  import sys
- import string
  
  MAXFD = 256     # Max number of file descriptors (os.getdtablesize()???)
--- 9,12 ----
***************
*** 23,26 ****
--- 22,27 ----
      by the factory functions popen2() and popen3()."""
  
+     sts = -1                    # Child not completed yet
+ 
      def __init__(self, cmd, capturestderr=0, bufsize=-1):
          """The parameter 'cmd' is the shell command to execute in a
***************
*** 29,34 ****
          The default is false.  If the 'bufsize' parameter is specified, it
          specifies the size of the I/O buffers to/from the child process."""
!         if type(cmd) == type(''):
!             cmd = ['/bin/sh', '-c', cmd]
          p2cread, p2cwrite = os.pipe()
          c2pread, c2pwrite = os.pipe()
--- 30,34 ----
          The default is false.  If the 'bufsize' parameter is specified, it
          specifies the size of the I/O buffers to/from the child process."""
!         _cleanup()
          p2cread, p2cwrite = os.pipe()
          c2pread, c2pwrite = os.pipe()
***************
*** 38,60 ****
          if self.pid == 0:
              # Child
!             os.close(0)
!             os.close(1)
!             if os.dup(p2cread) <> 0:
!                 sys.stderr.write('popen2: bad read dup\n')
!             if os.dup(c2pwrite) <> 1:
!                 sys.stderr.write('popen2: bad write dup\n')
              if capturestderr:
!                 os.close(2)
!                 if os.dup(errin) <> 2: pass
!             for i in range(3, MAXFD):
!                 try:
!                     os.close(i)
!                 except: pass
!             try:
!                 os.execvp(cmd[0], cmd)
!             finally:
!                 os._exit(1)
!             # Shouldn't come here, I guess
!             os._exit(1)
          os.close(p2cread)
          self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
--- 38,46 ----
          if self.pid == 0:
              # Child
!             os.dup2(p2cread, 0)
!             os.dup2(c2pwrite, 1)
              if capturestderr:
!                 os.dup2(errin, 2)
!             self._run_child(cmd)
          os.close(p2cread)
          self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
***************
*** 66,72 ****
          else:
              self.childerr = None
-         self.sts = -1 # Child not completed yet
          _active.append(self)
  
      def poll(self):
          """Return the exit status of the child process if it has finished,
--- 52,70 ----
          else:
              self.childerr = None
          _active.append(self)
  
+     def _run_child(self, cmd):
+         if type(cmd) == type(''):
+             cmd = ['/bin/sh', '-c', cmd]
+         for i in range(3, MAXFD):
+             try:
+                 os.close(i)
+             except:
+                 pass
+         try:
+             os.execvp(cmd[0], cmd)
+         finally:
+             os._exit(1)
+ 
      def poll(self):
          """Return the exit status of the child process if it has finished,
***************
*** 91,96 ****
  
  
  if sys.platform[:3] == "win":
!     def popen2(cmd, mode='t', bufsize=-1):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
--- 89,118 ----
  
  
+ class Popen4(Popen3):
+     childerr = None
+ 
+     def __init__(self, cmd, bufsize=-1):
+         _cleanup()
+         p2cread, p2cwrite = os.pipe()
+         c2pread, c2pwrite = os.pipe()
+         self.pid = os.fork()
+         if self.pid == 0:
+             # Child
+             os.dup2(p2cread, 0)
+             os.dup2(c2pwrite, 1)
+             os.dup2(c2pwrite, 2)
+             self._run_child(cmd)
+         os.close(p2cread)
+         self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
+         os.close(c2pwrite)
+         self.fromchild = os.fdopen(c2pread, 'r', bufsize)
+         _active.append(self)
+ 
+ 
  if sys.platform[:3] == "win":
!     # Some things don't make sense on non-Unix platforms.
!     del Popen3, Popen4, _active, _cleanup
! 
!     def popen2(cmd, bufsize=-1, mode='t'):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
***************
*** 98,116 ****
          w, r = os.popen2(cmd, mode, bufsize)
          return r, w
- else:
-     def popen2(cmd, mode='t', bufsize=-1):
-         """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
-         specified, it sets the buffer size for the I/O pipes.  The file objects
-         (child_stdout, child_stdin) are returned."""
-         if type(mode) is type(0) and bufsize == -1:
-             bufsize = mode
-             mode = 't'
-         assert mode in ('t', 'b')
-         _cleanup()
-         inst = Popen3(cmd, 0, bufsize)
-         return inst.fromchild, inst.tochild
  
! if sys.platform[:3] == "win":
!     def popen3(cmd, mode='t', bufsize=-1):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
--- 120,125 ----
          w, r = os.popen2(cmd, mode, bufsize)
          return r, w
  
!     def popen3(cmd, bufsize=-1, mode='t'):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
***************
*** 118,143 ****
          w, r, e = os.popen3(cmd, mode, bufsize)
          return r, w, e
  else:
!     def popen3(cmd, mode='t', bufsize=-1):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
          (child_stdout, child_stdin, child_stderr) are returned."""
-         if type(mode) is type(0) and bufsize == -1:
-             bufsize = mode
-             mode = 't'
-         assert mode in ('t', 'b')
-         _cleanup()
          inst = Popen3(cmd, 1, bufsize)
          return inst.fromchild, inst.tochild, inst.childerr
  
! if sys.platform[:3] == "win":
!     def popen4(cmd, mode='t', bufsize=-1):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
          (child_stdout_stderr, child_stdin) are returned."""
!         w, r = os.popen4(cmd, mode, bufsize)
!         return r, w
! else:
!     pass # not yet on unix
  
  
--- 127,158 ----
          w, r, e = os.popen3(cmd, mode, bufsize)
          return r, w, e
+ 
+     def popen4(cmd, bufsize=-1, mode='t'):
+         """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
+         specified, it sets the buffer size for the I/O pipes.  The file objects
+         (child_stdout_stderr, child_stdin) are returned."""
+         w, r = os.popen4(cmd, mode, bufsize)
+         return r, w
  else:
!     def popen2(cmd, bufsize=-1, mode='t'):
!         """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
!         specified, it sets the buffer size for the I/O pipes.  The file objects
!         (child_stdout, child_stdin) are returned."""
!         inst = Popen3(cmd, 0, bufsize)
!         return inst.fromchild, inst.tochild
! 
!     def popen3(cmd, bufsize=-1, mode='t'):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
          (child_stdout, child_stdin, child_stderr) are returned."""
          inst = Popen3(cmd, 1, bufsize)
          return inst.fromchild, inst.tochild, inst.childerr
  
!     def popen4(cmd, bufsize=-1, mode='t'):
          """Execute the shell command 'cmd' in a sub-process.  If 'bufsize' is
          specified, it sets the buffer size for the I/O pipes.  The file objects
          (child_stdout_stderr, child_stdin) are returned."""
!         inst = Popen4(cmd, bufsize)
!         return inst.fromchild, inst.tochild