original_docstring: launches a new Tor process with the given config.
  
      There may seem to be a ton of options, but don't panic: this
      method should be easy to use and most options can be ignored
      except for advanced use-cases. Calling with a completely empty
      TorConfig should Just Work::
  
          config = TorConfig()
          d = launch_tor(config, reactor)
          d.addCallback(...)
  
      Note that the incoming TorConfig instance is examined and several
      config options are acted upon appropriately:
  
      ``DataDirectory``: if supplied, a tempdir is not created, and the
      one supplied is not deleted.
  
      ``ControlPort``: if 0 (zero), a control connection is NOT
      established (and ``connection_creator`` is ignored). In this case
      we can't wait for Tor to bootstrap, and **you must kill the tor**
      yourself.
  
      ``User``: if this exists, we attempt to set ownership of the tempdir
      to this user (but only if our effective UID is 0).
  
      This method may set the following options on the supplied
      TorConfig object: ``DataDirectory, ControlPort,
      CookieAuthentication, __OwningControllerProcess`` and WILL call
      :meth:`txtorcon.TorConfig.save`
  
      :param config:
          an instance of :class:`txtorcon.TorConfig` with any
          configuration values you want.  If ``ControlPort`` isn't set,
          9052 is used; if ``DataDirectory`` isn't set, tempdir is used
          to create one (in this case, it will be deleted upon exit).
  
      :param reactor: a Twisted IReactorCore implementation (usually
          twisted.internet.reactor)
  
      :param tor_binary: path to the Tor binary to run. Tries to find the tor
          binary if unset.
  
      :param progress_updates: a callback which gets progress updates; gets as
           args: percent, tag, summary (FIXME make an interface for this).
  
      :param kill_on_stderr:
          When True (the default), if Tor prints anything on stderr we
          kill off the process, close the TorControlProtocol and raise
          an exception.
  
      :param stdout: a file-like object to which we write anything that
          Tor prints on stdout (just needs to support write()).
  
      :param stderr: a file-like object to which we write anything that
          Tor prints on stderr (just needs .write()). Note that we kill Tor
          off by default if anything appears on stderr; pass "no_kill=True"
          if you don't like the behavior.
  
      :param connection_creator: is mostly available to ease testing, so
          you probably don't want to supply this. If supplied, it is a
          callable that should return a Deferred that delivers an
          :api:`twisted.internet.interfaces.IProtocol <IProtocol>` or
          ConnectError.
          See :api:`twisted.internet.interfaces.IStreamClientEndpoint`.connect
          Note that this parameter is ignored if config.ControlPort == 0
  
      :return: a Deferred which callbacks with a TorProcessProtocol
          connected to the fully-bootstrapped Tor; this has a
          :class:`txtorcon.TorControlProtocol` instance as `.tor_protocol`. In
          Tor, ``__OwningControllerProcess`` will be set and TAKEOWNERSHIP will
          have been called, so if you close the TorControlProtocol the Tor should
          exit also (see `control-spec
          <https://gitweb.torproject.org/torspec.git/blob/HEAD:/control-spec.txt>`_
          3.23). Note that if ControlPort was 0, we don't connect at all
          and therefore don't wait for Tor to be bootstrapped. In this case, it's
          up to you to kill off the Tor you created.
  
      HACKS:
  
       1. It's hard to know when Tor has both (completely!) written its
          authentication cookie file AND is listening on the control
          port. It seems that waiting for the first 'bootstrap' message on
          stdout is sufficient. Seems fragile...and doesn't work 100% of
          the time, so FIXME look at Tor source.
      
docstring: launches a new Tor process with the given config.
  There may seem to be a ton of options, but don't panic: this
  method should be easy to use and most options can be ignored
  except for advanced use-cases. Calling with a completely empty
  TorConfig should Just Work:.
  
  
  
  Note that the incoming TorConfig instance is examined and several
  config options are acted upon appropriately.
  
  ``DataDirectory``: if supplied, a tempdir is not created, and the
  one supplied is not deleted.
  
  
  
  ``User``: if this exists, we attempt to set ownership of the tempdir
  to this user (but only if our effective UID is 0).
  
  This method may set the following options on the supplied
  TorConfig object: ``DataDirectory, ControlPort,
  CookieAuthentication, __OwningControllerProcess`` and WILL call
docstring_tokens: launches a new Tor process with the given config . There may seem to be a ton of options but don ' t panic : this method should be easy to use and most options can be ignored except for advanced use - cases . Calling with a completely empty TorConfig should Just Work : . Note that the incoming TorConfig instance is examined and several config options are acted upon appropriately . ` ` DataDirectory ` ` : if supplied a tempdir is not created and the one supplied is not deleted . ` ` User ` ` : if this exists we attempt to set ownership of the tempdir to this user ( but only if our effective UID is 0 ) . This method may set the following options on the supplied TorConfig object : ` ` DataDirectory ControlPort CookieAuthentication __OwningControllerProcess ` ` and WILL call
code: def launch_tor(config, reactor,
                 tor_binary=None,
                 progress_updates=None,
                 connection_creator=None,
                 timeout=None,
                 kill_on_stderr=True,
                 stdout=None, stderr=None):
      """launches a new Tor process with the given config.
  
      There may seem to be a ton of options, but don't panic: this
      method should be easy to use and most options can be ignored
      except for advanced use-cases. Calling with a completely empty
      TorConfig should Just Work::
  
          config = TorConfig()
          d = launch_tor(config, reactor)
          d.addCallback(...)
  
      Note that the incoming TorConfig instance is examined and several
      config options are acted upon appropriately:
  
      ``DataDirectory``: if supplied, a tempdir is not created, and the
      one supplied is not deleted.
  
      ``ControlPort``: if 0 (zero), a control connection is NOT
      established (and ``connection_creator`` is ignored). In this case
      we can't wait for Tor to bootstrap, and **you must kill the tor**
      yourself.
  
      ``User``: if this exists, we attempt to set ownership of the tempdir
      to this user (but only if our effective UID is 0).
  
      This method may set the following options on the supplied
      TorConfig object: ``DataDirectory, ControlPort,
      CookieAuthentication, __OwningControllerProcess`` and WILL call
      :meth:`txtorcon.TorConfig.save`
  
      :param config:
          an instance of :class:`txtorcon.TorConfig` with any
          configuration values you want.  If ``ControlPort`` isn't set,
          9052 is used; if ``DataDirectory`` isn't set, tempdir is used
          to create one (in this case, it will be deleted upon exit).
  
      :param reactor: a Twisted IReactorCore implementation (usually
          twisted.internet.reactor)
  
      :param tor_binary: path to the Tor binary to run. Tries to find the tor
          binary if unset.
  
      :param progress_updates: a callback which gets progress updates; gets as
           args: percent, tag, summary (FIXME make an interface for this).
  
      :param kill_on_stderr:
          When True (the default), if Tor prints anything on stderr we
          kill off the process, close the TorControlProtocol and raise
          an exception.
  
      :param stdout: a file-like object to which we write anything that
          Tor prints on stdout (just needs to support write()).
  
      :param stderr: a file-like object to which we write anything that
          Tor prints on stderr (just needs .write()). Note that we kill Tor
          off by default if anything appears on stderr; pass "no_kill=True"
          if you don't like the behavior.
  
      :param connection_creator: is mostly available to ease testing, so
          you probably don't want to supply this. If supplied, it is a
          callable that should return a Deferred that delivers an
          :api:`twisted.internet.interfaces.IProtocol <IProtocol>` or
          ConnectError.
          See :api:`twisted.internet.interfaces.IStreamClientEndpoint`.connect
          Note that this parameter is ignored if config.ControlPort == 0
  
      :return: a Deferred which callbacks with a TorProcessProtocol
          connected to the fully-bootstrapped Tor; this has a
          :class:`txtorcon.TorControlProtocol` instance as `.tor_protocol`. In
          Tor, ``__OwningControllerProcess`` will be set and TAKEOWNERSHIP will
          have been called, so if you close the TorControlProtocol the Tor should
          exit also (see `control-spec
          <https://gitweb.torproject.org/torspec.git/blob/HEAD:/control-spec.txt>`_
          3.23). Note that if ControlPort was 0, we don't connect at all
          and therefore don't wait for Tor to be bootstrapped. In this case, it's
          up to you to kill off the Tor you created.
  
      HACKS:
  
       1. It's hard to know when Tor has both (completely!) written its
          authentication cookie file AND is listening on the control
          port. It seems that waiting for the first 'bootstrap' message on
          stdout is sufficient. Seems fragile...and doesn't work 100% of
          the time, so FIXME look at Tor source.
      """
  
      # We have a slight problem with the approach: we need to pass a
      # few minimum values to a torrc file so that Tor will start up
      # enough that we may connect to it. Ideally, we'd be able to
      # start a Tor up which doesn't really do anything except provide
      # "AUTHENTICATE" and "GETINFO config/names" so we can do our
      # config validation.
  
      # the other option here is to simply write a torrc version of our
      # config and get Tor to load that...which might be the best
      # option anyway.
  
      # actually, can't we pass them all as command-line arguments?
      # could be pushing some limits for giant configs...
  
      if tor_binary is None:
          tor_binary = find_tor_binary()
      if tor_binary is None:
          # We fail right here instead of waiting for the reactor to start
          raise TorNotFound('Tor binary could not be found')
  
      # make sure we got things that have write() for stderr, stdout
      # kwargs
      for arg in [stderr, stdout]:
          if arg and not getattr(arg, "write", None):
              raise RuntimeError(
                  'File-like object needed for stdout or stderr args.')
  
      try:
          data_directory = config.DataDirectory
          user_set_data_directory = True
      except KeyError:
          user_set_data_directory = False
          data_directory = tempfile.mkdtemp(prefix='tortmp')
          config.DataDirectory = data_directory
  
          # Set ownership on the temp-dir to the user tor will drop privileges to
          # when executing as root.
          try:
              user = config.User
          except KeyError:
              pass
          else:
              if sys.platform in ('linux2', 'darwin') and os.geteuid() == 0:
                  os.chown(data_directory, pwd.getpwnam(user).pw_uid, -1)
  
      try:
          control_port = config.ControlPort
      except KeyError:
          control_port = 9052  # FIXME choose a random, unoccupied one?
          config.ControlPort = control_port
  
      # so, we support passing in ControlPort=0 -- not really sure if
      # this is a good idea (since then the caller has to kill the tor
      # off, etc), but at least one person has requested it :/
      if control_port != 0:
          config.CookieAuthentication = 1
          config.__OwningControllerProcess = os.getpid()
          if connection_creator is None:
              connection_creator = functools.partial(
                  TCP4ClientEndpoint(reactor, 'localhost', control_port).connect,
                  TorProtocolFactory()
              )
      else:
          connection_creator = None
  
      # NOTE well, that if we don't pass "-f" then Tor will merrily load
      # it's default torrc, and apply our options over top... :/
      config_args = ['-f', '/non-existant', '--ignore-missing-torrc']
  
      # ...now add all our config options on the command-line. This
      # avoids writing a temporary torrc.
      for (k, v) in config.config_args():
          config_args.append(k)
          config_args.append(v)
  
      # txtorlog.msg('Running with config:\n', ' '.join(config_args))
  
      process_protocol = TorProcessProtocol(
          connection_creator,
          progress_updates,
          config, reactor,
          timeout,
          kill_on_stderr,
          stdout,
          stderr
      )
  
      # we set both to_delete and the shutdown events because this
      # process might be shut down way before the reactor, but if the
      # reactor bombs out without the subprocess getting closed cleanly,
      # we'll want the system shutdown events triggered so the temporary
      # files get cleaned up either way
  
      # we don't want to delete the user's directories, just temporary
      # ones this method created.
      if not user_set_data_directory:
          process_protocol.to_delete = [data_directory]
          reactor.addSystemEventTrigger(
              'before', 'shutdown',
              functools.partial(delete_file_or_tree, data_directory)
          )
  
      try:
          log.msg('Spawning tor process with DataDirectory', data_directory)
          args = [tor_binary] + config_args
          transport = reactor.spawnProcess(
              process_protocol,
              tor_binary,
              args=args,
              env={'HOME': data_directory},
              path=data_directory
          )
          # FIXME? don't need rest of the args: uid, gid, usePTY, childFDs)
          transport.closeStdin()
  
      except RuntimeError as e:
          return defer.fail(e)
  
      if process_protocol.connected_cb:
          return process_protocol.connected_cb
      return defer.succeed(process_protocol)
code_tokens: def launch_tor ( config , reactor , tor_binary = None , progress_updates = None , connection_creator = None , timeout = None , kill_on_stderr = True , stdout = None , stderr = None ) : if tor_binary is None : tor_binary = find_tor_binary ( ) if tor_binary is None : raise TorNotFound ( 'Tor binary could not be found' ) for arg in [ stderr , stdout ] : if arg and not getattr ( arg , "write" , None ) : raise RuntimeError ( 'File-like object needed for stdout or stderr args.' ) try : data_directory = config . DataDirectory user_set_data_directory = True except KeyError : user_set_data_directory = False data_directory = tempfile . mkdtemp ( prefix = 'tortmp' ) config . DataDirectory = data_directory try : user = config . User except KeyError : pass else : if sys . platform in ( 'linux2' , 'darwin' ) and os . geteuid ( ) == 0 : os . chown ( data_directory , pwd . getpwnam ( user ) . pw_uid , - 1 ) try : control_port = config . ControlPort except KeyError : control_port = 9052 config . ControlPort = control_port if control_port != 0 : config . CookieAuthentication = 1 config . __OwningControllerProcess = os . getpid ( ) if connection_creator is None : connection_creator = functools . partial ( TCP4ClientEndpoint ( reactor , 'localhost' , control_port ) . connect , TorProtocolFactory ( ) ) else : connection_creator = None config_args = [ '-f' , '/non-existant' , '--ignore-missing-torrc' ] for ( k , v ) in config . config_args ( ) : config_args . append ( k ) config_args . append ( v ) process_protocol = TorProcessProtocol ( connection_creator , progress_updates , config , reactor , timeout , kill_on_stderr , stdout , stderr ) if not user_set_data_directory : process_protocol . to_delete = [ data_directory ] reactor . addSystemEventTrigger ( 'before' , 'shutdown' , functools . partial ( delete_file_or_tree , data_directory ) ) try : log . msg ( 'Spawning tor process with DataDirectory' , data_directory ) args = [ tor_binary ] + config_args transport = reactor . spawnProcess ( process_protocol , tor_binary , args = args , env = { 'HOME' : data_directory } , path = data_directory ) transport . closeStdin ( ) except RuntimeError as e : return defer . fail ( e ) if process_protocol . connected_cb : return process_protocol . connected_cb return defer . succeed ( process_protocol )
short_docstring: launches a new Tor process with the given config.
short_docstring_tokens: launches a new Tor process with the given config .
comment: """launches a new Tor process with the given config.
  
      There may seem to be a ton of options, but don't panic: this
      method should be easy to use and most options can be ignored
      except for advanced use-cases. Calling with a completely empty
      TorConfig should Just Work::
  
          config = TorConfig()
          d = launch_tor(config, reactor)
          d.addCallback(...)
  
      Note that the incoming TorConfig instance is examined and several
      config options are acted upon appropriately:
  
      ``DataDirectory``: if supplied, a tempdir is not created, and the
      one supplied is not deleted.
  
      ``ControlPort``: if 0 (zero), a control connection is NOT
      established (and ``connection_creator`` is ignored). In this case
      we can't wait for Tor to bootstrap, and **you must kill the tor**
      yourself.
  
      ``User``: if this exists, we attempt to set ownership of the tempdir
      to this user (but only if our effective UID is 0).
  
      This method may set the following options on the supplied
      TorConfig object: ``DataDirectory, ControlPort,
      CookieAuthentication, __OwningControllerProcess`` and WILL call
      :meth:`txtorcon.TorConfig.save`
  
      :param config:
          an instance of :class:`txtorcon.TorConfig` with any
          configuration values you want.  If ``ControlPort`` isn't set,
          9052 is used; if ``DataDirectory`` isn't set, tempdir is used
          to create one (in this case, it will be deleted upon exit).
  
      :param reactor: a Twisted IReactorCore implementation (usually
          twisted.internet.reactor)
  
      :param tor_binary: path to the Tor binary to run. Tries to find the tor
          binary if unset.
  
      :param progress_updates: a callback which gets progress updates; gets as
           args: percent, tag, summary (FIXME make an interface for this).
  
      :param kill_on_stderr:
          When True (the default), if Tor prints anything on stderr we
          kill off the process, close the TorControlProtocol and raise
          an exception.
  
      :param stdout: a file-like object to which we write anything that
          Tor prints on stdout (just needs to support write()).
  
      :param stderr: a file-like object to which we write anything that
          Tor prints on stderr (just needs .write()). Note that we kill Tor
          off by default if anything appears on stderr; pass "no_kill=True"
          if you don't like the behavior.
  
      :param connection_creator: is mostly available to ease testing, so
          you probably don't want to supply this. If supplied, it is a
          callable that should return a Deferred that delivers an
          :api:`twisted.internet.interfaces.IProtocol <IProtocol>` or
          ConnectError.
          See :api:`twisted.internet.interfaces.IStreamClientEndpoint`.connect
          Note that this parameter is ignored if config.ControlPort == 0
  
      :return: a Deferred which callbacks with a TorProcessProtocol
          connected to the fully-bootstrapped Tor; this has a
          :class:`txtorcon.TorControlProtocol` instance as `.tor_protocol`. In
          Tor, ``__OwningControllerProcess`` will be set and TAKEOWNERSHIP will
          have been called, so if you close the TorControlProtocol the Tor should
          exit also (see `control-spec
          <https://gitweb.torproject.org/torspec.git/blob/HEAD:/control-spec.txt>`_
          3.23). Note that if ControlPort was 0, we don't connect at all
          and therefore don't wait for Tor to be bootstrapped. In this case, it's
          up to you to kill off the Tor you created.
  
      HACKS:
  
       1. It's hard to know when Tor has both (completely!) written its
          authentication cookie file AND is listening on the control
          port. It seems that waiting for the first 'bootstrap' message on
          stdout is sufficient. Seems fragile...and doesn't work 100% of
          the time, so FIXME look at Tor source.
      """$SEP$# We have a slight problem with the approach: we need to pass a$SEP$# few minimum values to a torrc file so that Tor will start up$SEP$# enough that we may connect to it. Ideally, we'd be able to$SEP$# start a Tor up which doesn't really do anything except provide$SEP$# "AUTHENTICATE" and "GETINFO config/names" so we can do our$SEP$# config validation.$SEP$# the other option here is to simply write a torrc version of our$SEP$# config and get Tor to load that...which might be the best$SEP$# option anyway.$SEP$# actually, can't we pass them all as command-line arguments?$SEP$# could be pushing some limits for giant configs...$SEP$# We fail right here instead of waiting for the reactor to start$SEP$# make sure we got things that have write() for stderr, stdout$SEP$# kwargs$SEP$# Set ownership on the temp-dir to the user tor will drop privileges to$SEP$# when executing as root.$SEP$# FIXME choose a random, unoccupied one?$SEP$# so, we support passing in ControlPort=0 -- not really sure if$SEP$# this is a good idea (since then the caller has to kill the tor$SEP$# off, etc), but at least one person has requested it :/$SEP$# NOTE well, that if we don't pass "-f" then Tor will merrily load$SEP$# it's default torrc, and apply our options over top... :/$SEP$# ...now add all our config options on the command-line. This$SEP$# avoids writing a temporary torrc.$SEP$# txtorlog.msg('Running with config:\n', ' '.join(config_args))$SEP$# we set both to_delete and the shutdown events because this$SEP$# process might be shut down way before the reactor, but if the$SEP$# reactor bombs out without the subprocess getting closed cleanly,$SEP$# we'll want the system shutdown events triggered so the temporary$SEP$# files get cleaned up either way$SEP$# we don't want to delete the user's directories, just temporary$SEP$# ones this method created.$SEP$# FIXME? don't need rest of the args: uid, gid, usePTY, childFDs)