15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#!/usr/bin/env python
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Copyright 2012 the V8 project authors. All rights reserved.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# modification, are permitted provided that the following conditions are
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# met:
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#     * Redistributions of source code must retain the above copyright
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#       notice, this list of conditions and the following disclaimer.
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#     * Redistributions in binary form must reproduce the above
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#       copyright notice, this list of conditions and the following
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#       disclaimer in the documentation and/or other materials provided
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#       with the distribution.
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#     * Neither the name of Google Inc. nor the names of its
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#       contributors may be used to endorse or promote products derived
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#       from this software without specific prior written permission.
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import os
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import subprocess
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import sys
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)PIDFILE = "/tmp/v8-distributed-testing-server.pid"
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROOT = os.path.abspath(os.path.dirname(sys.argv[0]))
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _PrintUsage():
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  print("""Usage: python %s COMMAND
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Where COMMAND can be any of:
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  start     Starts the server. Forks to the background.
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  stop      Stops the server.
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  restart   Stops, then restarts the server.
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  setup     Creates or updates the environment for the server to run.
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  update    Alias for "setup".
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  trust <keyfile>  Adds the given public key to the list of trusted keys.
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  help      Displays this help text.
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  """ % sys.argv[0])
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _IsDaemonRunning():
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return os.path.exists(PIDFILE)
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _Cmd(cmd):
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  code = subprocess.call(cmd, shell=True)
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if code != 0:
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    print("Command '%s' returned error code %d" % (cmd, code))
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    sys.exit(code)
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def Update():
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Create directory for private data storage.
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data_dir = os.path.join(ROOT, "data")
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if not os.path.exists(data_dir):
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    os.makedirs(data_dir)
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Create directory for trusted public keys of peers (and self).
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  trusted_dir = os.path.join(ROOT, "trusted")
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if not os.path.exists(trusted_dir):
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    os.makedirs(trusted_dir)
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Install UltraJSON. It is much faster than Python's builtin json.
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  try:
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    import ujson  #@UnusedImport
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  except ImportError:
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Install pip if it doesn't exist.
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    code = subprocess.call("which pip > /dev/null", shell=True)
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if code != 0:
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      apt_get_code = subprocess.call("which apt-get > /dev/null", shell=True)
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if apt_get_code == 0:
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        print("Installing pip...")
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        _Cmd("sudo apt-get install python-pip")
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      else:
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        print("Please install pip on your machine. You can get it at: "
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              "http://www.pip-installer.org/en/latest/installing.html "
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              "or via your distro's package manager.")
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sys.exit(1)
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    print("Using pip to install UltraJSON...")
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _Cmd("sudo pip install ujson")
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Make sure we have a key pair for signing binaries.
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  privkeyfile = os.path.expanduser("~/.ssh/v8_dtest")
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if not os.path.exists(privkeyfile):
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _Cmd("ssh-keygen -t rsa -f %s -N '' -q" % privkeyfile)
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fingerprint = subprocess.check_output("ssh-keygen -lf %s" % privkeyfile,
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        shell=True)
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fingerprint = fingerprint.split(" ")[1].replace(":", "")[:16]
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  pubkeyfile = os.path.join(trusted_dir, "%s.pem" % fingerprint)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (not os.path.exists(pubkeyfile) or
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      os.path.getmtime(pubkeyfile) < os.path.getmtime(privkeyfile)):
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _Cmd("openssl rsa -in %s -out %s -pubout" % (privkeyfile, pubkeyfile))
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    with open(pubkeyfile, "a") as f:
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      f.write(fingerprint + "\n")
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    datafile = os.path.join(data_dir, "mypubkey")
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    with open(datafile, "w") as f:
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      f.write(fingerprint + "\n")
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Check out or update the server implementation in the current directory.
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  testrunner_dir = os.path.join(ROOT, "testrunner")
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if os.path.exists(os.path.join(testrunner_dir, "server/daemon.py")):
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _Cmd("cd %s; svn up" % testrunner_dir)
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else:
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    path = ("http://v8.googlecode.com/svn/branches/bleeding_edge/"
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            "tools/testrunner")
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _Cmd("svn checkout --force %s %s" % (path, testrunner_dir))
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Update this very script.
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  path = ("http://v8.googlecode.com/svn/branches/bleeding_edge/"
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          "tools/test-server.py")
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scriptname = os.path.abspath(sys.argv[0])
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  _Cmd("svn cat %s > %s" % (path, scriptname))
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Check out or update V8.
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  v8_dir = os.path.join(ROOT, "v8")
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if os.path.exists(v8_dir):
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _Cmd("cd %s; git fetch" % v8_dir)
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else:
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _Cmd("git clone git://github.com/v8/v8.git %s" % v8_dir)
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  print("Finished.")
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Handle "setup" here, because when executing that we can't import anything
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# else yet.
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)if __name__ == "__main__" and len(sys.argv) == 2:
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if sys.argv[1] in ("setup", "update"):
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if _IsDaemonRunning():
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      print("Please stop the server before updating. Exiting.")
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      sys.exit(1)
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Update()
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    sys.exit(0)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  # Other parameters are handled below.
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#==========================================================
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# At this point we can assume that the implementation is available,
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# so we can import it.
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)try:
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  from testrunner.server import constants
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  from testrunner.server import local_handler
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  from testrunner.server import main
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)except Exception, e:
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  print(e)
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  print("Failed to import implementation. Have you run 'setup'?")
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  sys.exit(1)
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _StartDaemon(daemon):
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if not os.path.isdir(os.path.join(ROOT, "v8")):
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    print("No 'v8' working directory found. Have you run 'setup'?")
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    sys.exit(1)
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  daemon.start()
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)if __name__ == "__main__":
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if len(sys.argv) == 2:
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    arg = sys.argv[1]
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if arg == "start":
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      daemon = main.Server(PIDFILE, ROOT)
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      _StartDaemon(daemon)
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    elif arg == "stop":
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      daemon = main.Server(PIDFILE, ROOT)
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      daemon.stop()
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    elif arg == "restart":
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      daemon = main.Server(PIDFILE, ROOT)
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      daemon.stop()
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      _StartDaemon(daemon)
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    elif arg in ("help", "-h", "--help"):
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      _PrintUsage()
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    elif arg == "status":
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if not _IsDaemonRunning():
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        print("Server not running.")
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      else:
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        print(local_handler.LocalQuery([constants.REQUEST_STATUS]))
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else:
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      print("Unknown command")
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      _PrintUsage()
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      sys.exit(2)
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  elif len(sys.argv) == 3:
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    arg = sys.argv[1]
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if arg == "approve":
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      filename = sys.argv[2]
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if not os.path.exists(filename):
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        print("%s does not exist.")
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sys.exit(1)
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      filename = os.path.abspath(filename)
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if _IsDaemonRunning():
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        response = local_handler.LocalQuery([constants.ADD_TRUSTED, filename])
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      else:
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        daemon = main.Server(PIDFILE, ROOT)
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        response = daemon.CopyToTrusted(filename)
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      print("Added certificate %s to trusted certificates." % response)
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else:
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      print("Unknown command")
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      _PrintUsage()
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      sys.exit(2)
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else:
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    print("Unknown command")
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    _PrintUsage()
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    sys.exit(2)
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  sys.exit(0)
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)