OpenSecurity/bin/cygwin.py
author mb
Wed, 26 Feb 2014 17:27:07 +0100
changeset 79 617009c32da0
parent 78 23551f635ca9
child 87 d5b04809faca
permissions -rwxr-xr-x
hibernate, wait_startup, and other changes
om@13
     1
#!/bin/env python
om@13
     2
# -*- coding: utf-8 -*-
om@13
     3
om@13
     4
# ------------------------------------------------------------
om@13
     5
# cygwin command
om@13
     6
# 
om@13
     7
# executes a cygwin command inside the opensecurity project
om@13
     8
#
mb@60
     9
# Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
mb@60
    10
#        Oliver Maurhart, <oliver.maurhart@ait.ac.at>
om@13
    11
#
om@13
    12
# Copyright (C) 2013 AIT Austrian Institute of Technology
om@13
    13
# AIT Austrian Institute of Technology GmbH
om@13
    14
# Donau-City-Strasse 1 | 1220 Vienna | Austria
om@13
    15
# http://www.ait.ac.at
om@13
    16
#
om@13
    17
# This program is free software; you can redistribute it and/or
om@13
    18
# modify it under the terms of the GNU General Public License
om@13
    19
# as published by the Free Software Foundation version 2.
om@13
    20
# 
om@13
    21
# This program is distributed in the hope that it will be useful,
om@13
    22
# but WITHOUT ANY WARRANTY; without even the implied warranty of
om@13
    23
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
om@13
    24
# GNU General Public License for more details.
om@13
    25
# 
om@13
    26
# You should have received a copy of the GNU General Public License
om@13
    27
# along with this program; if not, write to the Free Software
om@13
    28
# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
om@13
    29
# Boston, MA  02110-1301, USA.
om@13
    30
# ------------------------------------------------------------
om@13
    31
om@13
    32
om@13
    33
# ------------------------------------------------------------
om@13
    34
# imports
om@13
    35
om@13
    36
import os
om@13
    37
import subprocess
om@13
    38
import sys
mb@60
    39
import _winreg
mb@60
    40
from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
mb@78
    41
import threading
om@13
    42
# local
om@13
    43
from environment import Environment
mb@60
    44
from opensecurity_util import logger, setupLogger, OpenSecurityException
oliver@71
    45
om@13
    46
# ------------------------------------------------------------
om@13
    47
# code
om@13
    48
mb@60
    49
def once(theClass):
mb@60
    50
    """get the path to our local cygwin installment"""
mb@60
    51
    home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
mb@60
    52
    path_hint = [ 
mb@60
    53
        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin')), 
mb@60
    54
        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin64')), 
mb@60
    55
        os.path.abspath(os.path.join(home_drive, 'cygwin')),
mb@60
    56
        os.path.abspath(os.path.join(home_drive, 'cygwin64'))
mb@60
    57
    ]
mb@60
    58
    path_valid = [ p for p in path_hint if os.path.exists(p) ]
mb@60
    59
        
mb@60
    60
    theClass.cygwin_root = path_valid[0]
mb@60
    61
    theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep
mb@60
    62
    theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe')
mb@60
    63
    theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe')
oliver@64
    64
    theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe')
mb@60
    65
    theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe") 
mb@60
    66
    
mb@60
    67
    """get the path to the VirtualBox installation on this system"""
mb@60
    68
    try:
mb@60
    69
        k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\Oracle\VirtualBox')
mb@60
    70
        theClass.vbox_root = _winreg.QueryValueEx(k, 'InstallDir')[0]
mb@60
    71
        theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
mb@60
    72
        _winreg.CloseKey(k)
mb@60
    73
    except:
mb@60
    74
        pass
mb@60
    75
    return theClass
om@13
    76
mb@60
    77
@once
om@13
    78
class Cygwin(object):
mb@60
    79
    cygwin_root = ''
mb@60
    80
    cygwin_bin = ''
mb@60
    81
    cygwin_bash = ''
mb@60
    82
    cygwin_ssh = ''
oliver@64
    83
    cygwin_x11 = ''
mb@60
    84
    vbox_root = ''
mb@60
    85
    vbox_man = ''
mb@60
    86
    win_cmd = ''
om@13
    87
    """Some nifty methods working with Cygwin"""
om@13
    88
    
mb@60
    89
    def __call__(self, command, arguments, wait_return=True, window = False):
om@13
    90
        """make an instance of this object act as a function"""
mb@60
    91
        return self.execute(command, arguments, wait_return, window)
om@13
    92
om@13
    93
        
om@13
    94
    @staticmethod
om@13
    95
    def root():
mb@60
    96
        return Cygwin.cygwin_root
om@13
    97
mb@60
    98
    @staticmethod
mb@60
    99
    def bin():
mb@60
   100
        return Cygwin.cygwin_bin
mb@60
   101
    
mb@60
   102
    @staticmethod
mb@60
   103
    def bash():
mb@60
   104
        return Cygwin.cygwin_bash
mb@60
   105
    
mb@60
   106
    @staticmethod    
mb@60
   107
    def ssh():
mb@60
   108
        return Cygwin.cygwin_ssh
oliver@64
   109
oliver@64
   110
    @staticmethod    
oliver@64
   111
    def x11():
oliver@64
   112
        return Cygwin.cygwin_x11
mb@60
   113
    
mb@60
   114
    @staticmethod
mb@60
   115
    def vboxman():
mb@60
   116
        return Cygwin.vbox_man
mb@60
   117
    
mb@60
   118
    @staticmethod
mb@60
   119
    def cmd():
mb@60
   120
        return Cygwin.win_cmd
mb@60
   121
    
mb@78
   122
    executeLock = threading.Lock()
mb@60
   123
    #executes command on host system
mb@60
   124
    @staticmethod
mb@60
   125
    def execute(program, arguments, wait_return=True, window = False):
mb@79
   126
        _startupinfo = STARTUPINFO()
mb@79
   127
        if not window:
mb@79
   128
            _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
mb@79
   129
            _startupinfo.wShowWindow = _subprocess.SW_HIDE
mb@78
   130
mb@79
   131
            #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
mb@79
   132
        res_stderr = None
mb@79
   133
        try:
mb@79
   134
            process = Popen(executable=program, args=' ' + arguments, startupinfo = _startupinfo, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell = False)
mb@79
   135
            logger.debug('Launched: ' + program + ' ' + ''.join(arguments))
mb@79
   136
            if not wait_return:
mb@79
   137
                return [0, 'working in background', '']
mb@79
   138
            result = process.wait()
mb@79
   139
            res_stdout = process.stdout.read();
mb@79
   140
            res_stderr = process.stderr.read();
mb@79
   141
mb@79
   142
        except Exception as ex:
mb@79
   143
            res_stderr = ''.join(ex.args)
mb@79
   144
            result = -1 
mb@79
   145
        
mb@79
   146
        if result != 0:
mb@79
   147
            logger.error('Failed to execute cygwin command.\n\tcommand=' + program + ' ' + ''.join(arguments) + '\n' + res_stderr)
mb@79
   148
            raise OpenSecurityException('Failed to execute cygwin command.\n\tcommand=' + program + ' ' + ''.join(arguments) + '\n' + res_stderr)
mb@79
   149
            
mb@60
   150
        return result, res_stdout, res_stderr
mb@60
   151
    
mb@60
   152
    @staticmethod
mb@60
   153
    def vboxExecute(command, wait_return=True, window = False, bash_opts=''):
mb@79
   154
        if Cygwin.executeLock.acquire(True):
mb@79
   155
            retry = 0
mb@79
   156
            while retry < 3:
mb@79
   157
                try:
mb@79
   158
                    result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window)
mb@79
   159
                    Cygwin.executeLock.release()
mb@79
   160
                    return result
mb@79
   161
                except OpenSecurityException as inst:
mb@79
   162
                    retry+=1
mb@79
   163
            Cygwin.executeLock.release()
mb@79
   164
            raise inst
mb@79
   165
        return result
mb@79
   166
        
mb@60
   167
    
mb@60
   168
    @staticmethod
mb@60
   169
    def bashExecute(command, wait_return=True, window = False, bash_opts=''):
oliver@64
   170
        command = bash_opts + ' -l -c '  + command
mb@60
   171
        return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window)
mb@60
   172
    
mb@60
   173
    @staticmethod
mb@60
   174
    def cmdExecute(command, wait_return=True, window = False, bash_opts=''):
mb@60
   175
        command = ' /c ' + command 
mb@60
   176
        return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
om@13
   177
mb@60
   178
    # executes command over ssh on guest vm
mb@60
   179
    @staticmethod
mb@60
   180
    def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
mb@60
   181
        command = ' -v -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command        
mb@60
   182
        return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)     
mb@60
   183
    
mb@60
   184
    #machineFolder + '/' + vm_name + '/dvm_key
mb@60
   185
    #address = self.getHostOnlyIP(vm_name)
mb@60
   186
    #machineFolder = self.getDefaultMachineFolder()
mb@60
   187
    #machineFolder = Cygwin.cygwinPath(machineFolder)
mb@60
   188
    
mb@60
   189
    # executes command over ssh on guest vm with X forwarding
mb@60
   190
    @staticmethod
mb@60
   191
    def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
mb@60
   192
        return Cygwin.bashExecute('"DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\"' + certificate +'\\" ' + user_name + '@' + address + ' ' + command + '\"')
dyle@52
   193
om@13
   194
    @staticmethod
om@13
   195
    def is_X11_running():
om@13
   196
        """check if we can connect to a X11 running instance"""
mb@60
   197
        p = Cygwin.bashExecute('"DISPLAY=:0 /usr/bin/xset -q"')
mb@60
   198
        return p[0] == 0
om@13
   199
        
om@13
   200
        
om@13
   201
    @staticmethod
om@13
   202
    def start_X11():
om@13
   203
        """start X11 in the background (if not already running) on DISPLAY=:0"""
om@13
   204
        # do not start if already running
om@13
   205
        if Cygwin.is_X11_running():
mb@60
   206
            return           
om@13
   207
        # launch X11 (forget output and return immediately)
oliver@64
   208
        return Cygwin.execute(Cygwin.cygwin_x11, ':0 -multiwindow', wait_return = False, window = False)
mb@60
   209
    
mb@60
   210
    @staticmethod    
mb@60
   211
    def cygPath(path):
mb@60
   212
        cmd = '"/usr/bin/cygpath -u \\"' + path + '\\""'
mb@60
   213
        return Cygwin.bashExecute(cmd)[1].rstrip('\n')
om@13
   214
    
om@13
   215
# start
om@13
   216
if __name__ == "__main__":
mb@60
   217
    logger = setupLogger('Cygwin')
mb@60
   218
    c = Cygwin()
mb@60
   219
    logger.info(c.root())
mb@60
   220
    logger.info(c.bin())
mb@60
   221
    logger.info(c.bash())
mb@60
   222
    logger.info(c.ssh())
mb@60
   223
    
mb@60
   224
    c.cygPath('C:')
mb@60
   225
    c.start_X11()
om@13
   226
mb@60
   227
        
om@13
   228
    
om@13
   229