diff --git a/jhbuild/frontends/terminal.py b/jhbuild/frontends/terminal.py
index 048fa64..9a7b160 100644
--- a/jhbuild/frontends/terminal.py
+++ b/jhbuild/frontends/terminal.py
@@ -137,42 +137,24 @@ class TerminalBuildScript(buildscript.BuildScript):
 
 
     def execute(self, command, hint=None, cwd=None, extra_env=None):
-        if not command:
-            raise CommandError(_('No command given'))
+        capture_output = False
+        if hint in ('cvs', 'svn', 'hg-update.py'):
+            capture_output = True
+
+        if self.config.quiet_mode:
+            capture_output = True
 
-        kws = {
-            'close_fds': True
-            }
         if isinstance(command, (str, unicode)):
-            kws['shell'] = True
             pretty_command = command
         else:
             pretty_command = ' '.join(command)
 
         if not self.config.quiet_mode:
             print pretty_command
 
-        kws['stdin'] = subprocess.PIPE
-        if hint in ('cvs', 'svn', 'hg-update.py'):
-            kws['stdout'] = subprocess.PIPE
-            kws['stderr'] = subprocess.STDOUT
-        else:
-            kws['stdout'] = None
-            kws['stderr'] = None
-
-        if self.config.quiet_mode:
-            kws['stdout'] = subprocess.PIPE
-            kws['stderr'] = subprocess.STDOUT
-
-        if cwd is not None:
-            kws['cwd'] = cwd
-
-        if extra_env is not None:
-            kws['env'] = os.environ.copy()
-            kws['env'].update(extra_env)
-
         try:
-            p = subprocess.Popen(command, **kws)
+            p = cmds.get_subprocess(command=command, cwd=cwd, extra_env=extra_env,
+                                    capture_output=capture_output)
         except OSError, e:
             raise CommandError(str(e))
 
diff --git a/jhbuild/utils/cmds.py b/jhbuild/utils/cmds.py
index 1cd72f7..7b79d18 100644
--- a/jhbuild/utils/cmds.py
+++ b/jhbuild/utils/cmds.py
@@ -21,9 +21,126 @@ import os
 import re
 import select
 import subprocess
+import sys
+import time
 from signal import SIGINT
 from jhbuild.errors import CommandError
 
+# Wrapper around python's uglyass subprocess module. Its main purpose is to emulate unixisms
+# when we are running under windows.
+class jhprocess(subprocess.Popen):
+    __emulate_close_fds = False
+
+    def __init__(self, command, **kw_args):
+        if not isinstance(command, list):
+            command=command.strip()
+            command=command.split(' ')
+
+        if sys.platform.startswith('win'):
+            # ----------------------------------------
+            # THE MAIN WIN32 ON MSYS/CYGWIN HACKS
+            # ----------------------------------------
+            #Msys is smart about replacing paths on the shell. However autofoo scripts also
+            #have their own path checks that pickup mixed windows and unix paths and error in
+            #weird ways. In the interest of easy debugging, we replace all important occurances of
+            #windows-isms with unix isms in this function, even if msys can do some of them
+            # FIXME: what is this hack_prefix stuff?
+            HACK_PREFIX = 'C:\\msys\\'
+            def unixify_path(oldpath):
+                return oldpath.replace(HACK_PREFIX,'/').replace('\\','/')
+
+            #1) Start cmds in new shell otherwise it cant find them (the . confuses windows).
+            #   Also, some msys commands are in fact shell scripts (such as bunzip2) - these need
+            #   running in sh rather than directly through Windows.
+            if command[0].startswith('./'):
+                command = ['sh', command[0].replace('./','')] + command[1:]
+
+            for path in os.environ['PATH'].split(os.pathsep):
+                prog = os.path.abspath(os.path.join(path, command[0]))
+                # check if program has no extension or has .sh extension - this makes it a shell script
+                if os.path.exists(prog) or os.path.exists("%s.sh" % prog):
+                    command = ['sh', '-c', ' '.join([command[0]] + command[1:])]
+                    break
+
+            #2) Replace any path prefixes in command line args
+            for i in range(0,len(command)):
+                if command[i].count(HACK_PREFIX):
+                    command[i] = unixify_path(command[i])
+
+            #3) Replace any path prefixes in white listed env vars
+            envvars = [os.environ]
+            if 'env' in kw_args:
+                envvars.append(kw_args['env'])
+            HACK_ENV_VARS = ['PKG_CONFIG_PATH','CFLAGS','LDFLAGS']
+            for env in envvars:
+                if env != None:
+                    for k,v in env.items():
+                        if k in HACK_ENV_VARS and v.count(HACK_PREFIX):
+                            env[k] = unixify_path(v)
+
+            # 4) Can't use close_fd's on Windows - instead, we have to emulate its behavior!
+            if 'close_fds' in kw_args and kw_args['close_fds']==True:
+                kw_args['close_fds'] = False
+                self.__emulate_close_fds = True
+        subprocess.Popen.__init__(self, command, **kw_args)
+
+    def __del__(self):
+        if self.__emulate_close_fds:
+            for f in self.stdin, self.stdout, self.stderr:
+                #print f
+                # This somehow tells us if we are dealing with a pipe.
+                if isinstance(f, file) and f.name=='<fdopen>':
+                    #print 'Pipe'
+                    # Not that it actually matters.
+                    f.close()
+                    #print f
+            sys.stdout.flush()
+
+# output_file sends stdout to a file rather than a pipe. It is clobbered if it already exists.
+#
+# FIXME: should be able to move much of this function into jhprocess.
+def get_subprocess(command, cwd=None, extra_env=None, capture_output=False, quiet=False, output_file=None):
+    if not command:
+        raise CommandError('No command given')
+
+    kws = {
+        # Shell breaks things on windows (launches explorer) so
+        # Use Popen with a list instead of a string and make shell False
+        'shell'     :   False
+        }
+
+    kws['close_fds'] = True
+
+    #print output to console
+    kws['stdin'] = subprocess.PIPE
+    kws['stdout'] = None
+    kws['stderr'] = None
+
+    if output_file != None:
+        kws['stdout'] = open(output_file, 'w')
+
+    #need to capture the output to check for conflicts in vcs commands
+    elif capture_output == True:
+        kws['stdout'] = subprocess.PIPE
+        kws['stderr'] = subprocess.STDOUT
+
+    if cwd is not None:
+        kws['cwd'] = cwd
+
+    if extra_env is not None:
+        kws['env'] = os.environ.copy()
+        kws['env'].update(extra_env)
+
+    try:
+        p = jhprocess(command, **kws)
+    except OSError, e:
+        if not quiet:
+            sys.stderr.write('Error: %s\n' % str(e))
+        raise CommandError(str(e))
+
+    return p
+
+
 def get_output(cmd, cwd=None, extra_env=None, get_stderr = True):
     '''Return the output (stdout and stderr) from the command.
 
@@ -44,17 +161,16 @@ def get_output(cmd, cwd=None, extra_env=None, get_stderr = True):
         kws['env'] = os.environ.copy()
         kws['env'].update(extra_env)
 
+    kws['close_fds'] = True
+
+    kws['stdin'] = subprocess.PIPE
+    kws['stdout'] = subprocess.PIPE
     if get_stderr:
-        stderr_output = subprocess.STDOUT
+        kws['stderr'] = subprocess.STDOUT
     else:
-        stderr_output = subprocess.PIPE
+        kws['stderr'] = subprocess.PIPE
     try:
-        p = subprocess.Popen(cmd,
-                             close_fds=True,
-                             stdin=subprocess.PIPE,
-                             stdout=subprocess.PIPE,
-                             stderr=stderr_output,
-                             **kws)
+        p = jhprocess(cmd, **kws);
     except OSError, e:
         raise CommandError(str(e))
     stdout, stderr = p.communicate()

