second commit
This commit is contained in:
112
env/lib/python3.11/site-packages/shellingham/posix/__init__.py
vendored
Normal file
112
env/lib/python3.11/site-packages/shellingham/posix/__init__.py
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from .._core import SHELL_NAMES, ShellDetectionFailure
|
||||
from . import proc, ps
|
||||
|
||||
# Based on QEMU docs: https://www.qemu.org/docs/master/user/main.html
|
||||
QEMU_BIN_REGEX = re.compile(
|
||||
r"""qemu-
|
||||
(alpha
|
||||
|armeb
|
||||
|arm
|
||||
|m68k
|
||||
|cris
|
||||
|i386
|
||||
|x86_64
|
||||
|microblaze
|
||||
|mips
|
||||
|mipsel
|
||||
|mips64
|
||||
|mips64el
|
||||
|mipsn32
|
||||
|mipsn32el
|
||||
|nios2
|
||||
|ppc64
|
||||
|ppc
|
||||
|sh4eb
|
||||
|sh4
|
||||
|sparc
|
||||
|sparc32plus
|
||||
|sparc64
|
||||
)""",
|
||||
re.VERBOSE,
|
||||
)
|
||||
|
||||
|
||||
def _iter_process_parents(pid, max_depth=10):
|
||||
"""Select a way to obtain process information from the system.
|
||||
|
||||
* `/proc` is used if supported.
|
||||
* The system `ps` utility is used as a fallback option.
|
||||
"""
|
||||
for impl in (proc, ps):
|
||||
try:
|
||||
iterator = impl.iter_process_parents(pid, max_depth)
|
||||
except EnvironmentError:
|
||||
continue
|
||||
return iterator
|
||||
raise ShellDetectionFailure("compatible proc fs or ps utility is required")
|
||||
|
||||
|
||||
def _get_login_shell(proc_cmd):
|
||||
"""Form shell information from SHELL environ if possible."""
|
||||
login_shell = os.environ.get("SHELL", "")
|
||||
if login_shell:
|
||||
proc_cmd = login_shell
|
||||
else:
|
||||
proc_cmd = proc_cmd[1:]
|
||||
return (os.path.basename(proc_cmd).lower(), proc_cmd)
|
||||
|
||||
|
||||
_INTERPRETER_SHELL_NAMES = [
|
||||
(re.compile(r"^python(\d+(\.\d+)?)?$"), {"xonsh"}),
|
||||
]
|
||||
|
||||
|
||||
def _get_interpreter_shell(proc_name, proc_args):
|
||||
"""Get shell invoked via an interpreter.
|
||||
|
||||
Some shells are implemented on, and invoked with an interpreter, e.g. xonsh
|
||||
is commonly executed with an executable Python script. This detects what
|
||||
script the interpreter is actually running, and check whether that looks
|
||||
like a shell.
|
||||
|
||||
See sarugaku/shellingham#26 for rational.
|
||||
"""
|
||||
for pattern, shell_names in _INTERPRETER_SHELL_NAMES:
|
||||
if not pattern.match(proc_name):
|
||||
continue
|
||||
for arg in proc_args:
|
||||
name = os.path.basename(arg).lower()
|
||||
if os.path.isfile(arg) and name in shell_names:
|
||||
return (name, arg)
|
||||
return None
|
||||
|
||||
|
||||
def _get_shell(cmd, *args):
|
||||
if cmd.startswith("-"): # Login shell! Let's use this.
|
||||
return _get_login_shell(cmd)
|
||||
name = os.path.basename(cmd).lower()
|
||||
if name == "rosetta" or QEMU_BIN_REGEX.fullmatch(name):
|
||||
# If the current process is Rosetta or QEMU, this likely is a
|
||||
# containerized process. Parse out the actual command instead.
|
||||
cmd = args[0]
|
||||
args = args[1:]
|
||||
name = os.path.basename(cmd).lower()
|
||||
if name in SHELL_NAMES: # Command looks like a shell.
|
||||
return (name, cmd)
|
||||
shell = _get_interpreter_shell(name, args)
|
||||
if shell:
|
||||
return shell
|
||||
return None
|
||||
|
||||
|
||||
def get_shell(pid=None, max_depth=10):
|
||||
"""Get the shell that the supplied pid or os.getpid() is running in."""
|
||||
pid = str(pid or os.getpid())
|
||||
for proc_args, _, _ in _iter_process_parents(pid, max_depth):
|
||||
shell = _get_shell(*proc_args)
|
||||
if shell:
|
||||
return shell
|
||||
return None
|
Reference in New Issue
Block a user