commit 95cd487cc30c86d62f6ae44cc41cf44129d917ad Author: Damian Johnson atagar@torproject.org Date: Fri Jul 8 16:30:17 2011 -0700
Starting Tor instance at wizard completion
This starts (or attempts to start) a Tor instance when the wizard finishes. Currently this just works for the basic use case where we have the permissions necessary to start Tor. --- src/cli/controller.py | 13 ++++++++++ src/cli/wizard.py | 51 +++++++++++++++++++++++++++----------- src/resources/torrcTemplate.txt | 1 + src/util/torConfig.py | 2 +- 4 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/src/cli/controller.py b/src/cli/controller.py index c9ab6e7..633296e 100644 --- a/src/cli/controller.py +++ b/src/cli/controller.py @@ -3,6 +3,7 @@ Main interface loop for arm, periodically redrawing the screen and issuing user input to the proper panels. """
+import os import time import curses import threading @@ -25,6 +26,7 @@ from util import connections, conf, enum, log, panel, sysTools, torConfig, torTo ARM_CONTROLLER = None
CONFIG = {"startup.events": "N3", + "startup.dataDirectory": "~/.arm", "startup.blindModeEnabled": False, "features.panels.show.graph": True, "features.panels.show.log": True, @@ -366,6 +368,17 @@ class Controller: if redraw: controlPanel.redraw(True) else: self._forceRedraw = True
+ def getDataDirectory(self): + """ + Provides the path where arm's resources are being placed. The path ends + with a slash and is created if it doesn't already exist. + """ + + dataDir = CONFIG["startup.dataDirectory"] + if not dataDir.endswith("/"): dataDir += "/" + if not os.path.exists(dataDir): os.makedirs(dataDir) + return os.path.expanduser(dataDir) + def isDone(self): """ True if arm should be terminated, false otherwise. diff --git a/src/cli/wizard.py b/src/cli/wizard.py index 946ecd1..3ab3b9d 100644 --- a/src/cli/wizard.py +++ b/src/cli/wizard.py @@ -5,13 +5,16 @@ that's used by arm to run its own tor instance.
import os import sys +import shutil import functools import curses
import cli.popups import cli.controller
-from util import connections, enum, log, torConfig, uiTools +from TorCtl import TorCtl + +from util import connections, enum, log, torConfig, torTools, uiTools
# template used to generate the torrc TORRC_TEMPLATE = "resources/torrcTemplate.txt" @@ -72,8 +75,7 @@ MSG_COLOR = "green" OPTION_COLOR = "yellow" DISABLED_COLOR = "cyan"
-CONFIG = {"startup.dataDirectory": "~/.arm", - "wizard.message.role": "", +CONFIG = {"wizard.message.role": "", "wizard.message.relay": "", "wizard.message.exit": "", "wizard.message.bridge": "", @@ -251,6 +253,7 @@ def showWizard():
# remembers the last selection made on the type prompt page relaySelection = RelayType.RELAY + controller = cli.controller.getController()
while True: if relayType == None: @@ -265,18 +268,36 @@ def showWizard(): elif selection == NEXT: generatedTorrc = getTorrc(relayType, config)
- dataDir = CONFIG["startup.dataDirectory"] - if not dataDir.endswith("/"): dataDir += "/" - torrcLocation = os.path.expanduser(dataDir) + "torrc" - - cli.controller.getController().requestRedraw(True) + torrcLocation = controller.getDataDirectory() + "torrc" + controller.requestRedraw(True) confirmationSelection = showConfirmationDialog(generatedTorrc, torrcLocation)
if confirmationSelection == NEXT: - log.log(log.NOTICE, "Resulting torrc:\n%s" % generatedTorrc) - break # TODO: implement next screen - elif confirmationSelection == CANCEL: + log.log(log.INFO, "Writing torrc to '%s':\n%s" % (torrcLocation, generatedTorrc)) + + # if the torrc already exists then save it to a _bak file + if os.path.exists(torrcLocation): + shutil.copy(torrcLocation, torrcLocation + "_bak") + + # writes the torrc contents + torrcFile = open(torrcLocation, "w") + torrcFile.write(generatedTorrc) + torrcFile.close() + + try: + os.system("tor --quiet -f %s&" % torrcLocation) + torctlConn, authType, authValue = TorCtl.preauth_connect(controlPort = 9052) + + if authType == TorCtl.AUTH_TYPE.COOKIE: + torctlConn.authenticate(authValue) + torTools.getConn().init(torctlConn) + else: + raise IOError("unexpected authentication type '%s'" % authType) + except IOError, exc: + log.log(log.WARN, "Unable to start tor: %s" % exc) + break + elif confirmationSelection == CANCEL: break
# redraws screen to clear away the dialog we just showed cli.controller.getController().requestRedraw(True) @@ -464,9 +485,9 @@ def getTorrc(relayType, config): templateOptions["BURST"] = "%i %s" % (int(relayRateComp[0]) * 2, " ".join(relayRateComp[1:]))
# exit notice will be in our data directory - dataDir = CONFIG["startup.dataDirectory"] - if not dataDir.endswith("/"): dataDir += "/" - templateOptions["NOTICE_PATH"] = os.path.expanduser(dataDir) + "exit-notice.html" + dataDir = cli.controller.getController().getDataDirectory() + templateOptions["NOTICE_PATH"] = dataDir + "exit-notice.html" + templateOptions["LOG_ENTRY"] = "notice file %stor-log" % dataDir
policyCategories = [] if not config[Options.POLICY].getValue(): @@ -564,7 +585,7 @@ def showConfirmationDialog(torrcContents, torrcLocation): div = option.find("#") if div != -1: option, comment = option[:div], option[div:]
- div = option.find(" ") + div = option.strip().find(" ") if div != -1: option, arg = option[:div], option[div:]
drawX = 2 + xOffset diff --git a/src/resources/torrcTemplate.txt b/src/resources/torrcTemplate.txt index abedd7f..072f847 100644 --- a/src/resources/torrcTemplate.txt +++ b/src/resources/torrcTemplate.txt @@ -9,6 +9,7 @@ [NEWLINE] ControlPort 9052 # port controllers can connect to CookieAuthentication 1 # method for controller authentication +Log [LOG_ENTRY] # location to log notices, warnings, and errors
[IF RELAY | EXIT | BRIDGE] RunAsDaemon 1 # runs as a background process diff --git a/src/util/torConfig.py b/src/util/torConfig.py index e5f1cb2..8510c7a 100644 --- a/src/util/torConfig.py +++ b/src/util/torConfig.py @@ -930,7 +930,7 @@ def renderTorrc(template, options, commentIndent = 30): comment = "# %s" % comment.strip()
# parses the argument from the option - if " " in parsedLine: + if " " in parsedLine.strip(): option, arg = parsedLine.split(" ", 1) option = option.strip() else: