1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Cygwin: workaround for ksh to execute #!-less scripts with itself

On Cygwin, ksh does not execute scripts without a #! path in a fork
of the ksh process as it does on other systems. Reproducer (run
from ksh):

  $ cat test.sh
  echo "${BASH_VERSION:-not bash}"
  echo "${.sh.version}"
  $ chmod +x test.sh
  $ ./test.sh
  4.4.12(3)-release
  ./test.sh: line 2: ${.sh.version}: bad substitution

The script was executed in bash instead of ksh.

After this fix, the output on Cygwin is like ksh on other systems:

  not bash
  Version AJM 93u+m/1.1.0-alpha+dev 2022-01-26

This also fixes a number of regression test failures, as quite a
few tests create and execute temp scripts without a hashbang path.

Analysis: On Cygwin, execve(2) happily executes shell scripts
without a #! path with /bin/sh (which is bash --posix). However,
ksh relies on execve(2) executing binaries or #! only, as it uses
an ENOEXEC failure to decide whether to fork and execute a #!-less
shell script with a reinitialized copy of itself via exscript().

src/cmd/ksh93/sh/path.c: path_spawn():
- Look at the magic first two bytes of the file; if it is "MZ"
  (Mark Zbikowski, originator of the .exe format) or "#!", continue
  as normal, otherwise simulate an ENOEXEC failure from execve(2)
  which will cause ksh to fall back on #!-less script execution.
This commit is contained in:
Martijn Dekker 2022-01-26 04:20:56 +00:00
parent 172becffea
commit fe268fcc91
3 changed files with 29 additions and 2 deletions

5
NEWS
View file

@ -3,6 +3,11 @@ For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0
Any uppercase BUG_* names are modernish shell bug IDs.
2022-01-26:
- On Cygwin, ksh now executes scripts that do not have a #! path itself,
like it does on other systems, instead of with /bin/sh.
2022-01-24:
- Fixed a crashing bug in history expansion that could occur when using the "&"

View file

@ -21,7 +21,7 @@
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2022-01-24" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_DATE "2022-01-26" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2022 Contributors to ksh " SH_RELEASE_FORK
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

View file

@ -2,7 +2,7 @@
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* Copyright (c) 2020-2021 Contributors to ksh 93u+m *
* Copyright (c) 2020-2022 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
@ -1214,6 +1214,28 @@ pid_t path_spawn(const char *opath,register char **argv, char **envp, Pathcomp_t
path = sp;
}
#endif /* SHELLMAGIC */
#if __CYGWIN__
/*
* On Cygwin, execve(2) happily executes shell scripts without a #! path with /bin/sh (which is bash --posix).
* However, ksh relies on execve(2) executing binaries or #! only, as it uses an ENOEXEC failure to decide
* whether to fork and execute a #!-less shell script with a reinitialized copy of itself via exscript() below.
* So, simulate that failure if the file is not a Windows executable or a script with a #! path.
*/
if((n = sh_open(opath,O_RDONLY,0)) >= 0)
{
uint16_t mz;
r = !(read(n,&mz,2)==2 && (mz==0x5A4D || mz==0x2123)); /* "MZ" or "#!" */
sh_close(n);
}
else
r = 0;
if(r)
{
pid = -1;
errno = ENOEXEC;
}
else
#endif
#if SHOPT_PFSH
if(spawn && !sh_isoption(SH_PFSH))
pid = _spawnveg(opath, &argv[0], envp, spawn>>1);