summaryrefslogtreecommitdiffstats
path: root/sshuttle
diff options
context:
space:
mode:
authorBrian May <brian@linuxpenguins.xyz>2015-11-16 08:41:25 +1100
committerBrian May <brian@linuxpenguins.xyz>2015-11-16 09:09:01 +1100
commitba1cf58a6cbe4953f6e012c10d5a66964d22a21f (patch)
tree6f2ca41c8b8416dd78a30c2367512060c8a49c25 /sshuttle
parentdd8e68b6dcb0a8b10d4949d07f5b3dd949af5409 (diff)
Add Python 3.5 support.
Diffstat (limited to 'sshuttle')
-rw-r--r--sshuttle/__main__.py8
-rw-r--r--sshuttle/assembler.py2
-rw-r--r--sshuttle/client.py93
-rw-r--r--sshuttle/compat/__init__.py0
-rw-r--r--sshuttle/compat/ssubprocess.py1296
-rw-r--r--sshuttle/firewall.py30
-rw-r--r--sshuttle/helpers.py2
-rw-r--r--sshuttle/hostwatch.py14
-rw-r--r--sshuttle/options.py6
-rw-r--r--sshuttle/server.py14
-rw-r--r--sshuttle/ssh.py14
-rw-r--r--sshuttle/ssnet.py49
-rw-r--r--sshuttle/ssyslog.py2
-rwxr-xr-xsshuttle/stresstest.py20
-rw-r--r--sshuttle/ui-macos/main.py20
-rw-r--r--sshuttle/ui-macos/models.py2
-rw-r--r--sshuttle/ui-macos/my.py2
17 files changed, 145 insertions, 1429 deletions
diff --git a/sshuttle/__main__.py b/sshuttle/__main__.py
index 2c8aed6..1144c68 100644
--- a/sshuttle/__main__.py
+++ b/sshuttle/__main__.py
@@ -1,8 +1,8 @@
import sys
import re
import socket
-import helpers
-import options
+import sshuttle.helpers as helpers
+import sshuttle.options as options
import sshuttle.client as client
import sshuttle.server as server
import sshuttle.firewall as firewall
@@ -145,7 +145,7 @@ o = options.Options(optspec)
if opt.daemon:
opt.syslog = 1
if opt.wrap:
- import ssnet
+ import sshuttle.ssnet as ssnet
ssnet.MAX_CHANNEL = int(opt.wrap)
helpers.verbose = opt.verbose
@@ -230,7 +230,7 @@ try:
log('Abnormal exit code detected, failing...' % return_code)
sys.exit(return_code)
-except Fatal, e:
+except Fatal as e:
log('fatal: %s\n' % e)
sys.exit(99)
except KeyboardInterrupt:
diff --git a/sshuttle/assembler.py b/sshuttle/assembler.py
index be5b957..ee2b12e 100644
--- a/sshuttle/assembler.py
+++ b/sshuttle/assembler.py
@@ -18,7 +18,7 @@ while 1:
setattr(sys.modules[parent], parent_name, module)
code = compile(content, name, "exec")
- exec code in module.__dict__
+ exec(code, module.__dict__)
sys.modules[name] = module
else:
break
diff --git a/sshuttle/client.py b/sshuttle/client.py
index 55be9b3..cf4fc91 100644
--- a/sshuttle/client.py
+++ b/sshuttle/client.py
@@ -3,12 +3,12 @@ import errno
import re
import signal
import time
-import sshuttle.compat.ssubprocess as ssubprocess
-import helpers
+import subprocess as ssubprocess
+import sshuttle.helpers as helpers
import os
import sshuttle.ssnet as ssnet
import sshuttle.ssh as ssh
-import ssyslog
+import sshuttle.ssyslog as ssyslog
import sys
from sshuttle.ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper
from sshuttle.helpers import log, debug1, debug2, debug3, Fatal, islocal, \
@@ -124,7 +124,7 @@ def check_daemon(pidfile):
_pidname = os.path.abspath(pidfile)
try:
oldpid = open(_pidname).read(1024)
- except IOError, e:
+ except IOError as e:
if e.errno == errno.ENOENT:
return # no pidfile, ok
else:
@@ -138,7 +138,7 @@ def check_daemon(pidfile):
return # invalid pidfile, ok
try:
os.kill(oldpid, 0)
- except OSError, e:
+ except OSError as e:
if e.errno == errno.ESRCH:
os.unlink(_pidname)
return # outdated pidfile, ok
@@ -157,7 +157,7 @@ def daemonize():
if os.fork():
os._exit(0)
- outfd = os.open(_pidname, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0666)
+ outfd = os.open(_pidname, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o666)
try:
os.write(outfd, '%d\n' % os.getpid())
finally:
@@ -179,7 +179,7 @@ def daemonize():
def daemon_cleanup():
try:
os.unlink(_pidname)
- except OSError, e:
+ except OSError as e:
if e.errno == errno.ENOENT:
pass
else:
@@ -215,7 +215,7 @@ def original_dst(sock):
assert(socket.htons(proto) == socket.AF_INET)
ip = '%d.%d.%d.%d' % (a, b, c, d)
return (ip, port)
- except socket.error, e:
+ except socket.error as e:
if e.args[0] == errno.ENOPROTOOPT:
return sock.getsockname()
raise
@@ -251,7 +251,7 @@ class MultiListener:
if self.v4:
try:
self.v4.listen(backlog)
- except socket.error, e:
+ except socket.error as e:
# on some systems v4 bind will fail if the v6 suceeded,
# in this case the v6 socket will receive v4 too.
if e.errno == errno.EADDRINUSE and self.v6:
@@ -321,17 +321,22 @@ class FirewallClient:
self.p = ssubprocess.Popen(argv, stdout=s1, preexec_fn=setup)
e = None
break
- except OSError, e:
+ except OSError as e:
pass
self.argv = argv
s1.close()
- self.pfile = s2.makefile('wb+')
+ if sys.version_info < (3, 0):
+ # python 2.7
+ self.pfile = s2.makefile('wb+')
+ else:
+ # python 3.5
+ self.pfile = s2.makefile('rwb')
if e:
log('Spawning firewall manager: %r\n' % self.argv)
raise Fatal(e)
line = self.pfile.readline()
self.check()
- if line[0:5] != 'READY':
+ if line[0:5] != b'READY':
raise Fatal('%r expected READY, got %r' % (self.argv, line))
self.method = line[6:-1]
@@ -341,22 +346,26 @@ class FirewallClient:
raise Fatal('%r returned %d' % (self.argv, rv))
def start(self):
- self.pfile.write('ROUTES\n')
- for (family, ip, width) in self.subnets_include + self.auto_nets:
- self.pfile.write('%d,%d,0,%s\n' % (family, width, ip))
- for (family, ip, width) in self.subnets_exclude:
- self.pfile.write('%d,%d,1,%s\n' % (family, width, ip))
- self.pfile.write('GO\n')
+ self.pfile.write(b'ROUTES\n')
+ try:
+ for (family, ip, width) in self.subnets_include + self.auto_nets:
+ self.pfile.write(b'%d,%d,0,%s\n' % (family, width, ip.encode("ASCII")))
+ for (family, ip, width) in self.subnets_exclude:
+ self.pfile.write(b'%d,%d,1,%s\n' % (family, width, ip.encode("ASCII")))
+ except Exception as e:
+ debug1("exception occured %r" % e)
+ raise
+ self.pfile.write(b'GO\n')
self.pfile.flush()
line = self.pfile.readline()
self.check()
- if line != 'STARTED\n':
+ if line != b'STARTED\n':
raise Fatal('%r expected STARTED, got %r' % (self.argv, line))
def sethostip(self, hostname, ip):
assert(not re.search(r'[^-\w]', hostname))
assert(not re.search(r'[^0-9.]', ip))
- self.pfile.write('HOST %s,%s\n' % (hostname, ip))
+ self.pfile.write(b'HOST %s,%s\n' % (hostname, ip))
self.pfile.flush()
def done(self):
@@ -390,7 +399,7 @@ def onaccept_tcp(listener, method, mux, handlers):
global _extra_fd
try:
sock, srcip = listener.accept()
- except socket.error, e:
+ except socket.error as e:
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
debug1('Rejected incoming connection: too many open files!\n')
# free up an fd so we can eat the connection
@@ -403,9 +412,9 @@ def onaccept_tcp(listener, method, mux, handlers):
return
else:
raise
- if method == "tproxy":
+ if method == b"tproxy":
dstip = sock.getsockname()
- elif method == "pf":
+ elif method == b"pf":
dstip = pf_dst(sock)
else:
dstip = original_dst(sock)
@@ -420,8 +429,8 @@ def onaccept_tcp(listener, method, mux, handlers):
log('warning: too many open channels. Discarded connection.\n')
sock.close()
return
- mux.send(chan, ssnet.CMD_TCP_CONNECT, '%d,%s,%s' %
- (sock.family, dstip[0], dstip[1]))
+ mux.send(chan, ssnet.CMD_TCP_CONNECT, b'%d,%s,%d' %
+ (sock.family, dstip[0].encode("ASCII"), dstip[1]))
outwrap = MuxWrapper(mux, chan)
handlers.append(Proxy(SockWrapper(sock, sock), outwrap))
expire_connections(time.time(), mux)
@@ -439,7 +448,7 @@ def udp_done(chan, data, method, family, dstip):
sender.bind(srcip)
sender.sendto(data, dstip)
sender.close()
- except socket.error, e:
+ except socket.error as e:
debug1('-- ignored socket error sending UDP data: %r\n' % e)
@@ -471,7 +480,7 @@ def dns_done(chan, data, method, sock, srcip, dstip, mux):
debug3('dns_done: channel=%d src=%r dst=%r\n' % (chan, srcip, dstip))
del mux.channels[chan]
del dnsreqs[chan]
- if method == "tproxy":
+ if method == b"tproxy":
debug3('doing send from %r to %r\n' % (srcip, dstip,))
sender = socket.socket(sock.family, socket.SOCK_DGRAM)
sender.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -487,7 +496,7 @@ def dns_done(chan, data, method, sock, srcip, dstip, mux):
def ondns(listener, method, mux, handlers):
now = time.time()
srcip, dstip, data = recv_udp(listener, 4096)
- if method == "tproxy" and not dstip:
+ if method == b"tproxy" and not dstip:
debug1(
"-- ignored UDP from %r: "
"couldn't determine destination IP address\n" % (srcip,))
@@ -517,7 +526,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
ssh_cmd, remotename, python,
stderr=ssyslog._p and ssyslog._p.stdin,
options=dict(latency_control=latency_control, method=method))
- except socket.error, e:
+ except socket.error as e:
if e.args[0] == errno.EPIPE:
raise Fatal("failed to establish ssh session (1)")
else:
@@ -525,17 +534,17 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
mux = Mux(serversock, serversock)
handlers.append(mux)
- expected = 'SSHUTTLE0001'
+ expected = b'SSHUTTLE0001'
try:
v = 'x'
- while v and v != '\0':
+ while v and v != b'\0':
v = serversock.recv(1)
v = 'x'
- while v and v != '\0':
+ while v and v != b'\0':
v = serversock.recv(1)
initstring = serversock.recv(len(expected))
- except socket.error, e:
+ except socket.error as e:
if e.args[0] == errno.ECONNRESET:
raise Fatal("failed to establish ssh session (2)")
else:
@@ -549,7 +558,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
raise Fatal('expected server init string %r; got %r'
% (expected, initstring))
debug1('connected.\n')
- print 'Connected.'
+ print('Connected.')
sys.stdout.flush()
if daemon:
daemonize()
@@ -616,7 +625,7 @@ def main(listenip_v6, listenip_v4,
if daemon:
try:
check_daemon(pidfile)
- except Fatal, e:
+ except Fatal as e:
log("%s\n" % e)
return 5
debug1('Starting sshuttle proxy.\n')
@@ -624,7 +633,7 @@ def main(listenip_v6, listenip_v4,
if recvmsg is not None:
debug1("recvmsg %s support enabled.\n" % recvmsg)
- if method == "tproxy":
+ if method == b"tproxy":
if recvmsg is not None:
debug1("tproxy UDP support enabled.\n")
udp = True
@@ -643,7 +652,7 @@ def main(listenip_v6, listenip_v4,
ports = [0, ]
else:
# if at least one port missing, we have to search
- ports = xrange(12300, 9000, -1)
+ ports = range(12300, 9000, -1)
# search for free ports and try to bind
last_e = None
@@ -688,7 +697,7 @@ def main(listenip_v6, listenip_v4,
udp_listener.bind(lv6, lv4)
bound = True
break
- except socket.error, e:
+ except socket.error as e:
if e.errno == errno.EADDRINUSE:
last_e = e
else:
@@ -708,7 +717,7 @@ def main(listenip_v6, listenip_v4,
nslist += resolvconf_nameservers()
# search for spare port for DNS
debug2('Binding DNS:')
- ports = xrange(12300, 9000, -1)
+ ports = range(12300, 9000, -1)
for port in ports:
debug2(' %d' % port)
dns_listener = MultiListener(socket.SOCK_DGRAM)
@@ -731,7 +740,7 @@ def main(listenip_v6, listenip_v4,
dns_listener.bind(lv6, lv4)
bound = True
break
- except socket.error, e:
+ except socket.error as e:
if e.errno == errno.EADDRINUSE:
last_e = e
else:
@@ -750,7 +759,7 @@ def main(listenip_v6, listenip_v4,
subnets_exclude, dnsport_v6, dnsport_v4, nslist,
method, udp)
- if fw.method == "tproxy":
+ if fw.method == b"tproxy":
tcp_listener.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)
if udp_listener:
udp_listener.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)
@@ -767,7 +776,7 @@ def main(listenip_v6, listenip_v4,
if dns_listener.v6 is not None:
dns_listener.v6.setsockopt(SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
- if fw.method == "pf":
+ if fw.method == b"pf":
global pf_command_file
pf_command_file = fw.pfile
diff --git a/sshuttle/compat/__init__.py b/sshuttle/compat/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/sshuttle/compat/__init__.py
+++ /dev/null
diff --git a/sshuttle/compat/ssubprocess.py b/sshuttle/compat/ssubprocess.py
deleted file mode 100644
index 87797e6..0000000
--- a/sshuttle/compat/ssubprocess.py
+++ /dev/null
@@ -1,1296 +0,0 @@
-# subprocess - Subprocesses with accessible I/O streams
-#
-# For more information about this module, see PEP 324.
-#
-# This module should remain compatible with Python 2.2, see PEP 291.
-#
-# Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se>
-#
-# Licensed to PSF under a Contributor Agreement.
-# See http://www.python.org/2.4/license for licensing details.
-
-r"""subprocess - Subprocesses with accessible I/O streams
-
-This module allows you to spawn processes, connect to their
-input/output/error pipes, and obtain their return codes. This module
-intends to replace several other, older modules and functions, like:
-
-os.system
-os.spawn*
-os.popen*
-popen2.*
-commands.*
-
-Information about how the subprocess module can be used to replace these
-modules and functions can be found below.
-
-
-
-Using the subprocess module
-===========================
-This module defines one class called Popen:
-
-class Popen(args, bufsize=0, executable=None,
- stdin=None, stdout=None, stderr=None,
- preexec_fn=None, close_fds=False, shell=False,
- cwd=None, env=None, universal_newlines=False,
- startupinfo=None, creationflags=0):
-
-
-Arguments are:
-
-args should be a string, or a sequence of program arguments. The
-program to execute is normally the first item in the args sequence or
-string, but can be explicitly set by using the executable argument.
-
-On UNIX, with shell=False (default): In this case, the Popen class
-uses os.execvp() to execute the child program. args should normally
-be a sequence. A string will be treated as a sequence with the string
-as the only item (the program to execute).
-
-On UNIX, with shell=True: If args is a string, it specifies the
-command string to execute through the shell. If args is a sequence,
-the first item specifies the command string, and any additional items
-will be treated as additional shell arguments.
-
-On Windows: the Popen class uses CreateProcess() to execute the child
-program, which operates on strings. If args is a sequence, it will be
-converted to a string using the list2cmdline method. Please note that
-not all MS Windows applications interpret the command line the same
-way: The list2cmdline is designed for applications using the same
-rules as the MS C runtime.
-
-bufsize, if given, has the same meaning as the corresponding argument
-to the built-in open() function: 0 means unbuffered, 1 means line
-buffered, any other positive value means use a buffer of
-(approximately) that size. A negative bufsize means to use the system
-default, which usually means fully buffered. The default value for
-bufsize is 0 (unbuffered).
-
-stdin, stdout and stderr specify the executed programs' standard
-input, standard output and standard error file handles, respectively.
-Valid values are PIPE, an existing file descriptor (a positive
-integer), an existing file object, and None. PIPE indicates that a
-new pipe to the child should be created. With None, no redirection
-will occur; the child's file handles will be inherited from the
-parent. Additionally, stderr can be STDOUT, which indicates that the
-stderr data from the applications should be captured into the same
-file handle as for stdout.
-
-If preexec_fn is set to a callable object, this object will be called
-in the child process just before the child is executed.
-
-If close_fds is true, all file descriptors except 0, 1 and 2 will be
-closed before the child process is executed.
-
-if shell is true, the specified command will be executed through the
-shell.
-
-If cwd is not None, the current directory will be changed to cwd
-before the child is executed.
-
-If env is not None, it defines the environment variables for the new
-process.
-
-If universal_newlines is true, the file objects stdout and stderr are
-opened as a text files, but lines may be terminated by any of '\n',
-the Unix end-of-line convention, '\r', the Macintosh convention or
-'\r\n', the Windows convention. All of these external representations
-are seen as '\n' by the Python program. Note: This feature is only
-available if Python is built with universal newline support (the
-default). Also, the newlines attribute of the file objects stdout,
-stdin and stderr are not updated by the communicate() method.
-
-The startupinfo and creationflags, if given, will be passed to the
-underlying CreateProcess() function. They can specify things such as
-appearance of the main window and priority for the new process.
-(Windows only)
-
-
-This module also defines two shortcut functions:
-
-call(*popenargs, **kwargs):
- Run command with arguments. Wait for command to complete, then
- return the returncode attribute.
-
- The arguments are the same as for the Popen constructor. Example:
-
- retcode = call(["ls", "-l"])
-
-check_call(*popenargs, **kwargs):
- Run command with arguments. Wait for command to complete. If the
- exit code was zero then return, otherwise raise
- CalledProcessError. The CalledProcessError object will have the
- return code in the returncode attribute.
-
- The arguments are the same as for the Popen constructor. Example:
-
- check_call(["ls", "-l"])
-
-Exceptions
-----------
-Exceptions raised in the child process, before the new program has
-started to execute, will be re-raised in the parent. Additionally,
-the exception object will have one extra attribute called
-'child_traceback', which is a string containing traceback information
-from the childs point of view.
-
-The most common exception raised is OSError. This occurs, for
-example, when trying to execute a non-existent file. Applications
-should prepare for OSErrors.
-
-A ValueError will be raised if Popen is called with invalid arguments.
-
-check_call() will raise CalledProcessError, if the called process
-returns a non-zero return code.
-
-
-Security
---------
-Unlike some other popen functions, this implementation will never call
-/bin/sh implicitly. This means that all characters, including shell
-metacharacters, can safely be passed to child processes.
-
-
-Popen objects
-=============
-Instances of the Popen class have the following methods:
-
-poll()
- Check if child process has terminated. Returns returncode
- attribute.
-
-wait()
- Wait for child process to terminate. Returns returncode attribute.
-
-communicate(input=None)
- Interact with process: Send data to stdin. Read data from stdout
- and stderr, until end-of-file is reached. Wait for process to
- terminate. The optional input argument should be a string to be
- sent to the child process, or None, if no data should be sent to
- the child.
-
- communicate() returns a tuple (stdout, stderr).
-
- Note: The data read is buffered in memory, so do not use this
- method if the data size is large or unlimited.
-
-The following attributes are also available:
-
-stdin
- If the stdin argument is PIPE, this attribute is a file object
- that provides input to the child process. Otherwise, it is None.
-
-stdout
- If the stdout argument is PIPE, this attribute is a file object
- that provides output from the child process. Otherwise, it is
- None.
-
-stderr
- If the stderr argument is PIPE, this attribute is file object that
- provides error output from the child process. Otherwise, it is
- None.
-
-pid
- The process ID of the child process.
-
-returncode
- The child return code. A None value indicates that the process
- hasn't terminated yet. A negative value -N indicates that the
- child was terminated by signal N (UNIX only).
-
-
-Replacing older functions with the subprocess module
-====================================================
-In this section, "a ==> b" means that b can be used as a replacement
-for a.
-
-Note: All functions in this section fail (more or less) silently if
-the executed program cannot be found; this module raises an OSError
-exception.
-
-In the following examples, we assume that the subprocess module is
-imported with "from subprocess import *".
-
-
-Replacing /bin/sh shell backquote
----------------------------------
-output=`mycmd myarg`
-==>
-output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]
-
-
-Replacing shell pipe line
--------------------------
-output=`dmesg | grep hda`
-==>
-p1 = Popen(["dmesg"], stdout=PIPE)
-p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
-output = p2.communicate()[0]
-
-
-Replacing os.system()
----------------------
-sts = os.system("mycmd" + " myarg")
-==>
-p = Popen("mycmd" + " myarg", shell=True)
-pid, sts = os.waitpid(p.pid, 0)
-
-Note:
-
-* Calling the program through the shell is usually not required.
-
-* It's easier to look at the returncode attribute than the
- exitstatus.
-
-A more real-world example would look like this:
-
-try:
- retcode = call("mycmd" + " myarg", shell=True)
- if retcode < 0:
- print >>sys.stderr, "Child was terminated by signal", -retcode
- else:
- print >>sys.stderr, "Child returned", retcode
-except OSError, e:
- print >>sys.stderr, "Execution failed:", e
-
-
-Replacing os.spawn*
--------------------
-P_NOWAIT example:
-
-pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
-==>
-pid = Popen(["/bin/mycmd", "myarg"]).pid
-
-
-P_WAIT example:
-
-retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
-==>
-retcode = call(["/bin/mycmd", "myarg"])
-
-
-Vector example:
-
-os.spawnvp(os.P_NOWAIT, path, args)
-==>
-Popen([path] + args[1:])
-
-
-Environment example:
-
-os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
-==>
-Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})
-
-
-Replacing os.popen*
--------------------
-pipe = os.popen(cmd, mode='r', bufsize)
-==>
-pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout
-
-pipe = os.popen(cmd, mode='w', bufsize)
-==>
-pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin
-
-
-(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
-==>
-p = Popen(cmd, shell=True, bufsize=bufsize,
- stdin=PIPE, stdout=PIPE, close_fds=True)
-(child_stdin, child_stdout) = (p.stdin, p.stdout)
-
-
-(child_stdin,
- child_stdout,
- child_stderr) = os.popen3(cmd, mode, bufsize)
-==>
-p = Popen(cmd, shell=True, bufsize=bufsize,
- stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
-(child_stdin,
- child_stdout,
- child_stderr) = (p.stdin, p.stdout, p.stderr)
-
-
-(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
-==>
-p = Popen(cmd, shell=True, bufsize=bufsize,
- stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
-(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)
-
-
-Replacing popen2.*
-------------------
-Note: If the cmd argument to popen2 functions is a string, the command
-is executed through /bin/sh. If it is a list, the command is directly
-executed.
-
-(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
-==>
-p = Popen(["somestring"], shell=True, bufsize=bufsize
- stdin=PIPE, stdout=PIPE, close_fds=True)
-(child_stdout, child_stdin) = (p.stdout, p.stdin)
-
-
-(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
-==>
-p = Popen(["mycmd", "myarg"], bufsize=bufsize,
- stdin=PIPE, stdout=PIPE, close_fds=True)
-(child_stdout, child_stdin) = (p.stdout, p.stdin)
-
-The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen,
-except that:
-
-* subprocess.Popen raises an exception if the execution fails
-* the capturestderr argument is replaced with the stderr argument.
-* stdin=PIPE and stdout=PIPE must be specified.
-* popen2 closes all filedescriptors by default, but you have to specify
- close_fds=True with subprocess.Popen.
-"""
-
-import sys
-mswindows = (sys.platform == "win32")
-
-import os
-import types
-import traceback
-import gc
-import signal
-
-# Exception classes used by this module.
-
-
-class CalledProcessError(Exception):
- """This exception is raised when a process run by check_call() returns
- a non-zero exit status. The exit status will be stored in the
- returncode attribute."""
-
- def __init__(self, returncode, cmd):
- self.returncode = returncode
- self.cmd = cmd
-
- def __str__(self):
- return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
-
-
-if mswindows:
- import threading
- import msvcrt
- if 0: # <-- change this to use pywin32 instead of the _subprocess driver
- import pywintypes
- from win32api import GetStdHandle, STD_INPUT_HANDLE, \
- STD_OUTPUT_HANDLE, STD_ERROR_HANDLE
- from win32api import GetCurrentProcess, DuplicateHandle, \
- GetModuleFileName, GetVersion
- from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE
- from win32pipe import CreatePipe
- from win32process import CreateProcess, STARTUPINFO, \
- GetExitCodeProcess, STARTF_USESTDHANDLES, \
- STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE
- from win32process import TerminateProcess
- from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0
- else:
- from _subprocess import *
-
- class STARTUPINFO:
- dwFlags = 0
- hStdInput = None
- hStdOutput = None
- hStdError = None
- wShowWindow = 0
-
- class pywintypes:
- error = IOError
-else:
- import select
- import errno
- import fcntl
- import pickle
-
-__all__ = ["Popen", "PIPE", "STDOUT", "call",
- "check_call", "CalledProcessError"]
-
-try:
- MAXFD = os.sysconf("SC_OPEN_MAX")
-except:
- MAXFD = 256
-
-# True/False does not exist on 2.2.0
-# try:
-# False
-# except NameError:
-# False = 0
-# True = 1
-
-_active = []
-
-
-def _cleanup():
- for inst in _active[:]:
- if inst._internal_poll(_deadstate=sys.maxint) >= 0:
- try:
- _active.remove(inst)
- except ValueError:
- # This can happen if two threads create a new Popen instance.
- # It's harmless that it was already removed, so ignore.
- pass
-
-PIPE = -1
-STDOUT = -2
-
-
-def call(*popenargs, **kwargs):
- """Run command with arguments. Wait for command to complete, then
- return the returncode attribute.
-
- The arguments are the same as for the Popen constructor. Example:
-
- retcode = call(["ls", "-l"])
- """
- return Popen(*popenargs, **kwargs).wait()
-
-
-def check_call(*popenargs, **kwargs):
- """Run command with arguments. Wait for command to complete. If
- the exit code was zero then return, otherwise raise
- CalledProcessError. The CalledProcessError object will have the
- return code in the returncode attribute.
-
- The arguments are the same as for the Popen constructor. Example:
-
- check_call(["ls", "-l"])
- """
- retcode = call(*popenargs, **kwargs)
- cmd = kwargs.get("args")
- if cmd is None:
- cmd = popenargs[0]
- if retcode:
- raise CalledProcessError(retcode, cmd)
- return retcode
-
-
-def list2cmdline(seq):
- """
- Translate a sequence of arguments into a command line
- string, using the same rules as the MS C runtime:
-
- 1) Arguments are delimited by white space, which is either a
- space or a tab.
-
- 2) A string surrounded by double quotation marks is
- interpreted as a single argument, regardless of white space
- or pipe characters contained within. A quoted string can be
- embedded in an argument.
-
- 3) A double quotation mark preceded by a backslash is
- interpreted as a literal double quotation mark.
-
- 4) Backslashes are interpreted literally, unless they
- immediately precede a double quotation mark.
-
- 5) If backslashes immediately precede a double quotation mark,
- every pair of backslashes is interpreted as a literal
- backslash. If the number of backslashes is odd, the last
- backslash escapes the next double quotation mark as
- described in rule 3.
- """
-
- # See
- # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
- result = []
- needquote = False
- for arg in seq:
- bs_buf = []
-
- # Add a space to separate this argument from the others
- if result:
- result.append(' ')
-
- needquote = (" " in arg) or ("\t" in arg) or ("|" in arg) or not arg
- if needquote:
- result.append('"')
-
- for c in arg:
- if c == '\\':
- # Don't know if we need to double yet.
- bs_buf.append(c)
- elif c == '"':
- # Double backslashes.
- result.append('\\' * len(bs_buf) * 2)
- bs_buf = []
- result.append('\\"')
- else:
- # Normal char
- if bs_buf:
- result.extend(bs_buf)
- bs_buf = []
- result.append(c)
-
- # Add remaining backslashes, if any.
- if bs_buf:
- result.extend(bs_buf)
-
- if needquote:
- result.extend(bs_buf)
- result.append('"')
-
- return ''.join(result)
-
-
-def _closerange(start, max):
- try:
- os.closerange(start, max)
- except AttributeError:
- for i in xrange(start, max):
- try:
- os.close(i)
- except:
- pass
-
-
-class Popen(object):
-
- def __init__(self, args, bufsize=0, executable=None,
- stdin=None, stdout=None, stderr=None,
- preexec_fn=None, close_fds=False, shell=False,
- cwd=None, env=None, universal_newlines=False,