#NEWLINE# def launch_tor( config , reactor , tor_binary = None , progress_updates = None , connection_creator = None , timeout = None , kill_on_stderr = True , stdout = None , stderr = None ) : #NEWLINE# #INDENT# 'launches a new Tor process with the given config.\n\n    There may seem to be a ton of options, but don\'t panic: this\n    method should be easy to use and most options can be ignored\n    except for advanced use-cases. Calling with a completely empty\n    TorConfig should Just Work::\n\n        config = TorConfig()\n        d = launch_tor(config, reactor)\n        d.addCallback(...)\n\n    Note that the incoming TorConfig instance is examined and several\n    config options are acted upon appropriately:\n\n    ``DataDirectory``: if supplied, a tempdir is not created, and the\n    one supplied is not deleted.\n\n    ``ControlPort``: if 0 (zero), a control connection is NOT\n    established (and ``connection_creator`` is ignored). In this case\n    we can\'t wait for Tor to bootstrap, and **you must kill the tor**\n    yourself.\n\n    ``User``: if this exists, we attempt to set ownership of the tempdir\n    to this user (but only if our effective UID is 0).\n\n    This method may set the following options on the supplied\n    TorConfig object: ``DataDirectory, ControlPort,\n    CookieAuthentication, __OwningControllerProcess`` and WILL call\n    :meth:`txtorcon.TorConfig.save`\n\n    :param config:\n        an instance of :class:`txtorcon.TorConfig` with any\n        configuration values you want.  If ``ControlPort`` isn\'t set,\n        9052 is used; if ``DataDirectory`` isn\'t set, tempdir is used\n        to create one (in this case, it will be deleted upon exit).\n\n    :param reactor: a Twisted IReactorCore implementation (usually\n        twisted.internet.reactor)\n\n    :param tor_binary: path to the Tor binary to run. Tries to find the tor\n        binary if unset.\n\n    :param progress_updates: a callback which gets progress updates; gets as\n         args: percent, tag, summary (FIXME make an interface for this).\n\n    :param kill_on_stderr:\n        When True (the default), if Tor prints anything on stderr we\n        kill off the process, close the TorControlProtocol and raise\n        an exception.\n\n    :param stdout: a file-like object to which we write anything that\n        Tor prints on stdout (just needs to support write()).\n\n    :param stderr: a file-like object to which we write anything that\n        Tor prints on stderr (just needs .write()). Note that we kill Tor\n        off by default if anything appears on stderr; pass "no_kill=True"\n        if you don\'t like the behavior.\n\n    :param connection_creator: is mostly available to ease testing, so\n        you probably don\'t want to supply this. If supplied, it is a\n        callable that should return a Deferred that delivers an\n        :api:`twisted.internet.interfaces.IProtocol <IProtocol>` or\n        ConnectError.\n        See :api:`twisted.internet.interfaces.IStreamClientEndpoint`.connect\n        Note that this parameter is ignored if config.ControlPort == 0\n\n    :return: a Deferred which callbacks with a TorProcessProtocol\n        connected to the fully-bootstrapped Tor; this has a\n        :class:`txtorcon.TorControlProtocol` instance as `.tor_protocol`. In\n        Tor, ``__OwningControllerProcess`` will be set and TAKEOWNERSHIP will\n        have been called, so if you close the TorControlProtocol the Tor should\n        exit also (see `control-spec\n        <https://gitweb.torproject.org/torspec.git/blob/HEAD:/control-spec.txt>`_\n        3.23). Note that if ControlPort was 0, we don\'t connect at all\n        and therefore don\'t wait for Tor to be bootstrapped. In this case, it\'s\n        up to you to kill off the Tor you created.\n\n    HACKS:\n\n     1. It\'s hard to know when Tor has both (completely!) written its\n        authentication cookie file AND is listening on the control\n        port. It seems that waiting for the first \'bootstrap\' message on\n        stdout is sufficient. Seems fragile...and doesn\'t work 100% of\n        the time, so FIXME look at Tor source.\n    ' #NEWLINE# if ( tor_binary is None ) : #NEWLINE# #INDENT# tor_binary = find_tor_binary ( ) #NEWLINE# #UNINDENT# if ( tor_binary is None ) : #NEWLINE# #INDENT# raise TorNotFound ( 'Tor binary could not be found' ) #NEWLINE# #UNINDENT# for arg in [ stderr , stdout ] : #NEWLINE# #INDENT# if ( arg and ( not getattr ( arg , 'write' , None ) ) ) : #NEWLINE# #INDENT# raise RuntimeError ( 'File-like object needed for stdout or stderr args.' ) #NEWLINE# #UNINDENT# #UNINDENT# try : #NEWLINE# #INDENT# data_directory = config . DataDirectory #NEWLINE# user_set_data_directory = True #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# user_set_data_directory = False #NEWLINE# data_directory = tempfile . mkdtemp ( prefix = 'tortmp' ) #NEWLINE# config . DataDirectory = data_directory #NEWLINE# try : #NEWLINE# #INDENT# user = config . User #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# pass #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( sys . platform in ( 'linux2' , 'darwin' ) ) and ( os . geteuid ( ) == 0 ) ) : #NEWLINE# #INDENT# os . chown ( data_directory , pwd . getpwnam ( user ) . pw_uid , ( - 1 ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# try : #NEWLINE# #INDENT# control_port = config . ControlPort #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# control_port = 9052 #NEWLINE# config . ControlPort = control_port #NEWLINE# #UNINDENT# if ( control_port != 0 ) : #NEWLINE# #INDENT# config . CookieAuthentication = 1 #NEWLINE# config . __OwningControllerProcess = os . getpid ( ) #NEWLINE# if ( connection_creator is None ) : #NEWLINE# #INDENT# connection_creator = functools . partial ( TCP4ClientEndpoint ( reactor , 'localhost' , control_port ) . connect , TorProtocolFactory ( ) ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# connection_creator = None #NEWLINE# #UNINDENT# config_args = [ '-f' , '/non-existant' , '--ignore-missing-torrc' ] #NEWLINE# for ( k , v ) in config . config_args ( ) : #NEWLINE# #INDENT# config_args . append ( k ) #NEWLINE# config_args . append ( v ) #NEWLINE# #UNINDENT# process_protocol = TorProcessProtocol ( connection_creator , progress_updates , config , reactor , timeout , kill_on_stderr , stdout , stderr ) #NEWLINE# if ( not user_set_data_directory ) : #NEWLINE# #INDENT# process_protocol . to_delete = [ data_directory ] #NEWLINE# reactor . addSystemEventTrigger ( 'before' , 'shutdown' , functools . partial ( delete_file_or_tree , data_directory ) ) #NEWLINE# #UNINDENT# try : #NEWLINE# #INDENT# log . msg ( 'Spawning tor process with DataDirectory' , data_directory ) #NEWLINE# args = ( [ tor_binary ] + config_args ) #NEWLINE# transport = reactor . spawnProcess ( process_protocol , tor_binary , args = args , env = { #NEWLINE# #INDENT# 'HOME' : data_directory , #NEWLINE# #UNINDENT# } , path = data_directory ) #NEWLINE# transport . closeStdin ( ) #NEWLINE# #UNINDENT# except RuntimeError as e : #NEWLINE# #INDENT# return defer . fail ( e ) #NEWLINE# #UNINDENT# if process_protocol . connected_cb : #NEWLINE# #INDENT# return process_protocol . connected_cb #NEWLINE# #UNINDENT# return defer . succeed ( process_protocol )