| Index: third_party/pexpect/pexpect/utils.py
 | 
| diff --git a/third_party/pexpect/pexpect/utils.py b/third_party/pexpect/pexpect/utils.py
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..737f0eda05afb70140021999e48cc48e8a2d89f2
 | 
| --- /dev/null
 | 
| +++ b/third_party/pexpect/pexpect/utils.py
 | 
| @@ -0,0 +1,112 @@
 | 
| +import os
 | 
| +import sys
 | 
| +import stat
 | 
| +
 | 
| +
 | 
| +def is_executable_file(path):
 | 
| +    """Checks that path is an executable regular file, or a symlink towards one.
 | 
| +
 | 
| +    This is roughly ``os.path isfile(path) and os.access(path, os.X_OK)``.
 | 
| +    """
 | 
| +    # follow symlinks,
 | 
| +    fpath = os.path.realpath(path)
 | 
| +
 | 
| +    if not os.path.isfile(fpath):
 | 
| +        # non-files (directories, fifo, etc.)
 | 
| +        return False
 | 
| +
 | 
| +    mode = os.stat(fpath).st_mode
 | 
| +
 | 
| +    if (sys.platform.startswith('sunos')
 | 
| +            and os.getuid() == 0):
 | 
| +        # When root on Solaris, os.X_OK is True for *all* files, irregardless
 | 
| +        # of their executability -- instead, any permission bit of any user,
 | 
| +        # group, or other is fine enough.
 | 
| +        #
 | 
| +        # (This may be true for other "Unix98" OS's such as HP-UX and AIX)
 | 
| +        return bool(mode & (stat.S_IXUSR |
 | 
| +                            stat.S_IXGRP |
 | 
| +                            stat.S_IXOTH))
 | 
| +
 | 
| +    return os.access(fpath, os.X_OK)
 | 
| +
 | 
| +
 | 
| +def which(filename):
 | 
| +    '''This takes a given filename; tries to find it in the environment path;
 | 
| +    then checks if it is executable. This returns the full path to the filename
 | 
| +    if found and executable. Otherwise this returns None.'''
 | 
| +
 | 
| +    # Special case where filename contains an explicit path.
 | 
| +    if os.path.dirname(filename) != '' and is_executable_file(filename):
 | 
| +        return filename
 | 
| +    if 'PATH' not in os.environ or os.environ['PATH'] == '':
 | 
| +        p = os.defpath
 | 
| +    else:
 | 
| +        p = os.environ['PATH']
 | 
| +    pathlist = p.split(os.pathsep)
 | 
| +    for path in pathlist:
 | 
| +        ff = os.path.join(path, filename)
 | 
| +        if is_executable_file(ff):
 | 
| +            return ff
 | 
| +    return None
 | 
| +
 | 
| +
 | 
| +def split_command_line(command_line):
 | 
| +
 | 
| +    '''This splits a command line into a list of arguments. It splits arguments
 | 
| +    on spaces, but handles embedded quotes, doublequotes, and escaped
 | 
| +    characters. It's impossible to do this with a regular expression, so I
 | 
| +    wrote a little state machine to parse the command line. '''
 | 
| +
 | 
| +    arg_list = []
 | 
| +    arg = ''
 | 
| +
 | 
| +    # Constants to name the states we can be in.
 | 
| +    state_basic = 0
 | 
| +    state_esc = 1
 | 
| +    state_singlequote = 2
 | 
| +    state_doublequote = 3
 | 
| +    # The state when consuming whitespace between commands.
 | 
| +    state_whitespace = 4
 | 
| +    state = state_basic
 | 
| +
 | 
| +    for c in command_line:
 | 
| +        if state == state_basic or state == state_whitespace:
 | 
| +            if c == '\\':
 | 
| +                # Escape the next character
 | 
| +                state = state_esc
 | 
| +            elif c == r"'":
 | 
| +                # Handle single quote
 | 
| +                state = state_singlequote
 | 
| +            elif c == r'"':
 | 
| +                # Handle double quote
 | 
| +                state = state_doublequote
 | 
| +            elif c.isspace():
 | 
| +                # Add arg to arg_list if we aren't in the middle of whitespace.
 | 
| +                if state == state_whitespace:
 | 
| +                    # Do nothing.
 | 
| +                    None
 | 
| +                else:
 | 
| +                    arg_list.append(arg)
 | 
| +                    arg = ''
 | 
| +                    state = state_whitespace
 | 
| +            else:
 | 
| +                arg = arg + c
 | 
| +                state = state_basic
 | 
| +        elif state == state_esc:
 | 
| +            arg = arg + c
 | 
| +            state = state_basic
 | 
| +        elif state == state_singlequote:
 | 
| +            if c == r"'":
 | 
| +                state = state_basic
 | 
| +            else:
 | 
| +                arg = arg + c
 | 
| +        elif state == state_doublequote:
 | 
| +            if c == r'"':
 | 
| +                state = state_basic
 | 
| +            else:
 | 
| +                arg = arg + c
 | 
| +
 | 
| +    if arg != '':
 | 
| +        arg_list.append(arg)
 | 
| +    return arg_list
 | 
| 
 |