Runs 'command' on the underlying shell and keeps the stdout and
        stderr stream separate.

        Returns [stdout, stderr, exitCode]

def shell(command, **kwargs):
    """
        Runs 'command' on the underlying shell and keeps the stdout and
        stderr stream separate.

        Returns [stdout, stderr, exitCode]
    """
    b_stdoutflush       = False
    b_stderrflush       = False
    b_waitForChild      = True
    for key, val in kwargs.items():
        if key == 'stdoutflush':        b_stdoutflush   = val
        if key == 'stderrflush':        b_stderrflush   = val
        if key == 'waitForChild':       b_waitForChild  = val
    child = popen2.Popen3(command, 1) # capture stdout and stderr from command
    child.tochild.close()             # don't need to talk to child
    outfile = child.fromchild
    outfd = outfile.fileno()
    errfile = child.childerr
    errfd = errfile.fileno()
    makeNonBlocking(outfd)            # don't deadlock!
    makeNonBlocking(errfd)
    outdata = errdata = ''
    outeof = erreof = 0
    while b_waitForChild:
        ready = select.select([outfd,errfd],[],[]) # wait for input
        if outfd in ready[0]:
            outchunk = outfile.read()
            if b_stdoutflush: sys.stdout.write(outchunk)
            if outchunk == '': outeof = 1
            outdata = outdata + outchunk
        if errfd in ready[0]:
            errchunk = errfile.read()
            if b_stderrflush: sys.stderr.write(errchunk)
            if errchunk == '': erreof = 1
            errdata = errdata + errchunk
        if outeof and erreof: break
        select.select([],[],[],.1) # give a little time for buffers to fill
    err = child.wait()
    return outdata, errdata, err