diff options
author | Fred Drake <fdrake@acm.org> | 2000-09-28 19:07:53 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2000-09-28 19:07:53 (GMT) |
commit | d75e63a865b451c24e1a0516744a98d59691b4ff (patch) | |
tree | dd788aae5815b3456a5d626b88d3abd5f21c1ed2 | |
parent | 38cb9f1f174415d3b37fbaeb5d152d65525839d2 (diff) | |
download | cpython-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.py | 113 |
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(): |