1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)"""A module for the shell command."""
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import os
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import tempfile
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import cr
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class ShellCommand(cr.Command):
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  """The implementation of the shell command.
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  The shell command is the escape hatch that lets user run any program in the
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  same environment that cr would use if it were running it.
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  """
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def __init__(self):
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    super(ShellCommand, self).__init__()
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    self.help = 'Launch a shell'
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    self.description = ("""
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        If no arguments are present, this launches an interactive system
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        shell (ie bash) with the environment modified to that used for the
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        build systems.
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        If any arguments are present, they are used as a command line to run
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        in that shell.
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        This allows you to run commands that are not yet available natively
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        in cr.
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        """)
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def AddArguments(self, subparsers):
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    parser = super(ShellCommand, self).AddArguments(subparsers)
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    self.ConsumeArgs(parser, 'the shell')
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return parser
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  def Run(self):
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if cr.context.remains:
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      cr.Host.Shell(*cr.context.remains)
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    # If we get here, we are trying to launch an interactive shell
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    shell = os.environ.get('SHELL', None)
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if shell is None:
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      print 'Don\'t know how to run a shell on this system'
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    elif shell.endswith('bash'):
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ps1 = '[CR] ' + os.environ.get('PS1', '')
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      with tempfile.NamedTemporaryFile() as rcfile:
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        rcfile.write('source ~/.bashrc\nPS1="'+ps1+'"')
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        rcfile.flush()
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        cr.Host.Execute(shell, '--rcfile', rcfile.name)
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    else:
53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      cr.Host.Execute(shell)
54