summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2000-09-28 19:07:53 (GMT)
committerFred Drake <fdrake@acm.org>2000-09-28 19:07:53 (GMT)
commitd75e63a865b451c24e1a0516744a98d59691b4ff (patch)
treedd788aae5815b3456a5d626b88d3abd5f21c1ed2
parent38cb9f1f174415d3b37fbaeb5d152d65525839d2 (diff)
downloadcpython-d75e63a865b451c24e1a0516744a98d59691b4ff.zip
cpython-d75e63a865b451c24e1a0516744a98d59691b4ff.tar.gz
cpython-d75e63a865b451c24e1a0516744a98d59691b4ff.tar.bz2
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.
-rw-r--r--Lib/popen2.py113
1 files changed, 64 insertions, 49 deletions
diff --git a/Lib/popen2.py b/Lib/popen2.py
index 64c34d4..4580f58 100644
--- a/Lib/popen2.py
+++ b/Lib/popen2.py
@@ -8,7 +8,6 @@ and popen3(cmd) which return two or three pipes to the spawned command.
import os
import sys
-import string
MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???)
@@ -22,14 +21,15 @@ class Popen3:
"""Class representing a child process. Normally instances are created
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
sub-process. The 'capturestderr' flag, if true, specifies that
the object should capture standard error output of the child process.
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]
+ _cleanup()
p2cread, p2cwrite = os.pipe()
c2pread, c2pwrite = os.pipe()
if capturestderr:
@@ -37,25 +37,11 @@ class Popen3:
self.pid = os.fork()
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')
+ os.dup2(p2cread, 0)
+ os.dup2(c2pwrite, 1)
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.dup2(errin, 2)
+ self._run_child(cmd)
os.close(p2cread)
self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
os.close(c2pwrite)
@@ -65,9 +51,21 @@ class Popen3:
self.childerr = os.fdopen(errout, 'r', bufsize)
else:
self.childerr = None
- self.sts = -1 # Child not completed yet
_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,
or -1 if it hasn't finished yet."""
@@ -90,55 +88,72 @@ class Popen3:
return self.sts
+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":
- def popen2(cmd, mode='t', bufsize=-1):
+ # 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
(child_stdout, child_stdin) are returned."""
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):
+ 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."""
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 popen3(cmd, mode='t', bufsize=-1):
+ 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."""
- 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):
+ 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:
- pass # not yet on unix
+ inst = Popen4(cmd, bufsize)
+ return inst.fromchild, inst.tochild
def _test():