# Path: sshuttle/helpers.py
# def debug2(s):
#     if verbose >= 2:
#         log(s)
# 
# def which(file, mode=os.F_OK | os.X_OK):
#     """A wrapper around shutil.which() that searches a predictable set of
#     paths and is more verbose about what is happening. See get_path()
#     for more information.
#     """
#     path = get_path()
#     rv = _which(file, mode, path)
#     if rv:
#         debug2("which() found '%s' at %s" % (file, rv))
#     else:
#         debug2("which() could not find '%s' in %s" % (file, path))
#     return rv
# 
# def get_path():
#     """Returns a string of paths separated by os.pathsep.
# 
#     Users might not have all of the programs sshuttle needs in their
#     PATH variable (i.e., some programs might be in /sbin). Use PATH
#     and a hardcoded set of paths to search through. This function is
#     used by our which() and get_env() functions. If which() and the
#     subprocess environments differ, programs that which() finds might
#     not be found at run time (or vice versa).
#     """
#     path = []
#     if "PATH" in os.environ:
#         path += os.environ["PATH"].split(os.pathsep)
#     # Python default paths.
#     path += os.defpath.split(os.pathsep)
#     # /sbin, etc are not in os.defpath and may not be in PATH either.
#     # /bin/ and /usr/bin below are probably redundant.
#     path += ['/bin', '/usr/bin', '/sbin', '/usr/sbin']
# 
#     # Remove duplicates. Not strictly necessary.
#     path_dedup = []
#     for i in path:
#         if i not in path_dedup:
#             path_dedup.append(i)
# 
#     return os.pathsep.join(path_dedup)
# 
# class Fatal(Exception):
#     pass


import sys
import os
import re
import socket
import zlib
import importlib
import importlib.util
import subprocess as ssubprocess
import shlex
import ipaddress
import sshuttle.helpers as helpers
from shlex import quote
from urllib.parse import urlparse
from sshuttle.helpers import debug2, which, get_path, Fatal

def connect(ssh_cmd, rhostport, python, stderr, options):
    username, password, port, host = parse_hostport(rhostport)
    if username:
        rhost = "{}@{}".format(username, host)
    else:
        rhost = host

    z = zlib.compressobj(1)
    content = get_module_source('sshuttle.assembler')
    optdata = ''.join("%s=%r\n" % (k, v) for (k, v) in list(options.items()))
    optdata = optdata.encode("UTF8")
    content2 = (empackage(z, 'sshuttle') +
                empackage(z, 'sshuttle.cmdline_options', optdata) +
                empackage(z, 'sshuttle.helpers') +
                empackage(z, 'sshuttle.ssnet') +
                empackage(z, 'sshuttle.hostwatch') +
                empackage(z, 'sshuttle.server') +
                b"\n")

    # If the exec() program calls sys.exit(), it should exit python
    # and the sys.exit(98) call won't be reached (so we try to only
    # exit that way in the server). However, if the code that we
    # exec() simply returns from main, then we will return from
    # exec(). If the server's python process dies, it should stop
    # executing and also won't reach sys.exit(98).
    #
    # So, we shouldn't reach sys.exit(98) and we certainly shouldn't
    # reach it immediately after trying to start the server.
    pyscript = r"""

# Path: sshuttle/helpers.py
# def debug2(s):
#     if verbose >= 2:
#         log(s)
# 
# def which(file, mode=os.F_OK | os.X_OK):
#     """A wrapper around shutil.which() that searches a predictable set of
#     paths and is more verbose about what is happening. See get_path()
#     for more information.
#     """
#     path = get_path()
#     rv = _which(file, mode, path)
#     if rv:
#         debug2("which() found '%s' at %s" % (file, rv))
#     else:
#         debug2("which() could not find '%s' in %s" % (file, path))
#     return rv
# 
# def get_path():
#     """Returns a string of paths separated by os.pathsep.
# 
#     Users might not have all of the programs sshuttle needs in their
#     PATH variable (i.e., some programs might be in /sbin). Use PATH
#     and a hardcoded set of paths to search through. This function is
#     used by our which() and get_env() functions. If which() and the
#     subprocess environments differ, programs that which() finds might
#     not be found at run time (or vice versa).
#     """
#     path = []
#     if "PATH" in os.environ:
#         path += os.environ["PATH"].split(os.pathsep)
#     # Python default paths.
#     path += os.defpath.split(os.pathsep)
#     # /sbin, etc are not in os.defpath and may not be in PATH either.
#     # /bin/ and /usr/bin below are probably redundant.
#     path += ['/bin', '/usr/bin', '/sbin', '/usr/sbin']
# 
#     # Remove duplicates. Not strictly necessary.
#     path_dedup = []
#     for i in path:
#         if i not in path_dedup:
#             path_dedup.append(i)
# 
#     return os.pathsep.join(path_dedup)
# 
# class Fatal(Exception):
#     pass


# Path: sshuttle/ssh.py
import sys
import os
import re
import socket
import zlib
import importlib
import importlib.util
import subprocess as ssubprocess
import shlex
import ipaddress
import sshuttle.helpers as helpers
from shlex import quote
from urllib.parse import urlparse
from sshuttle.helpers import debug2, which, get_path, Fatal


def connect(ssh_cmd, rhostport, python, stderr, options):
    username, password, port, host = parse_hostport(rhostport)
    if username:
        rhost = "{}@{}".format(username, host)
    else:
        rhost = host

    z = zlib.compressobj(1)
    content = get_module_source('sshuttle.assembler')
    optdata = ''.join("%s=%r\n" % (k, v) for (k, v) in list(options.items()))
    optdata = optdata.encode("UTF8")
    content2 = (empackage(z, 'sshuttle') +
                empackage(z, 'sshuttle.cmdline_options', optdata) +
                empackage(z, 'sshuttle.helpers') +
                empackage(z, 'sshuttle.ssnet') +
                empackage(z, 'sshuttle.hostwatch') +
                empackage(z, 'sshuttle.server') +
                b"\n")

    # If the exec() program calls sys.exit(), it should exit python
    # and the sys.exit(98) call won't be reached (so we try to only
    # exit that way in the server). However, if the code that we
    # exec() simply returns from main, then we will return from
    # exec(). If the server's python process dies, it should stop
    # executing and also won't reach sys.exit(98).
    #
    # So, we shouldn't reach sys.exit(98) and we certainly shouldn't
    # reach it immediately after trying to start the server.
    pyscript = r"""

                import sys, os;