| 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
|
|
|