Merge pull request #3627 from laloch/argv0

Set argv[0] of a subprocess to the command as inserted by the user
This commit is contained in:
Anthony Scopatz 2020-08-05 10:41:48 -05:00 committed by GitHub
commit c40c9de9ad
Failed to generate hash of commit
4 changed files with 68 additions and 5 deletions

26
news/argv0.rst Normal file
View file

@ -0,0 +1,26 @@
**Added:**
* <news item>
**Changed:**
* Xonsh now launches subprocesses with their ``argv[0]`` argument containing
the command exactly as inserted by the user instead of setting it to the
resolved path of the executable. This is for consistency with bash and other
shells.
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

25
tests/bin/checkargv0.xsh Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env xonsh
res = True
script = """import os
path = "/proc/{}/cmdline".format(os.getpid())
with open(path, "r") as f:
lines = f.read().split("\x00")
print(lines[0])"""
def check(python):
argv0 = $(@(python) -c @(script)).rstrip()
if argv0 == python:
return True
print("Unexpected argv[0]: {} != {}".format(argv0, python))
return False
python = "python"
res &= check(python)
python = $(which -s python)
res &= check(python)
if res:
print("OK")

View file

@ -10,7 +10,9 @@ import xonsh
from xonsh.lib.os import indir
from tools import (
skip_if_on_msys,
skip_if_on_windows,
skip_if_on_darwin,
ON_WINDOWS,
ON_DARWIN,
ON_TRAVIS,
@ -681,3 +683,10 @@ aliases['echo'] = _echo
def test_single_command_return_code(cmd, exp_rtn):
_, _, rtn = run_xonsh(cmd, single_command=True)
assert rtn == exp_rtn
@skip_if_on_msys
@skip_if_on_windows
@skip_if_on_darwin
def test_argv0():
check_run_xonsh("checkargv0.xsh", None, "OK\n")

View file

@ -206,8 +206,9 @@ def _un_shebang(x):
def get_script_subproc_command(fname, args):
"""Given the name of a script outside the path, returns a list representing
an appropriate subprocess command to execute the script. Raises
PermissionError if the script is not executable.
an appropriate subprocess command to execute the script or None if
the argument is not readable or not a script. Raises PermissionError
if the script is not executable.
"""
# make sure file is executable
if not os.access(fname, os.X_OK):
@ -217,10 +218,10 @@ def get_script_subproc_command(fname, args):
# execute permissions but not read/write permissions. This enables
# things with the SUID set to be run. Needs to come before _is_binary()
# is called, because that function tries to read the file.
return [fname] + args
return None
elif _is_binary(fname):
# if the file is a binary, we should call it directly
return [fname] + args
return None
if ON_WINDOWS:
# Windows can execute various filetypes directly
# as given in PATHEXT
@ -730,7 +731,9 @@ class SubprocSpec:
if self.binary_loc is None:
return
try:
self.cmd = get_script_subproc_command(self.binary_loc, self.cmd[1:])
scriptcmd = get_script_subproc_command(self.binary_loc, self.cmd[1:])
if scriptcmd is not None:
self.cmd = scriptcmd
except PermissionError:
e = "xonsh: subprocess mode: permission denied: {0}"
raise XonshError(e.format(self.cmd[0]))