Embed cocmd.com interpreter for system() / open()

This change lets you use system() in an easier and portable way. The
problem with the call in the past has always been that bourne and
cmd.com on Windows have less than nothing in common, so pretty much the
only command system() could be used for across platforms was maybe echo.
cmd.exe is also a security liability due to its escaping rules.

Since cocmd.com implements 85% of what we need from bourne, in a really
tiny way, it makes perfect sense to be embedded in these functionss. We
get a huge performance boost too.

Fixes #644
This commit is contained in:
Justine Tunney 2022-10-02 15:29:57 -07:00
parent daca5499b9
commit 950a1b310b
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
9 changed files with 313 additions and 320 deletions

View file

@ -32,10 +32,14 @@
/**
* Launches program with system command interpreter.
*
* Warning: Caution is very much advised on Windows where this function
* currently delegates to CMD.EXE, which has notoriously mysterious and
* insecure escaping rules. Much better idea is to not use this at all,
* favoring instead explicit execve() invocations without using shells.
* This embeds the cocmd.com shell interpreter which supports a limited
* subset of the bourne shell that's significantly faster:
*
* - pipelines
* - single quotes
* - double quotes
* - input redirection, e.g. `<path`
* - output redirection, e.g. `>path`, `>>append`, `2>err.txt, `2>&1`
*
* @param cmdline is an interpreted Turing-complete command
* @return -1 if child process couldn't be created, otherwise a wait
@ -45,11 +49,7 @@ int system(const char *cmdline) {
int pid, wstatus;
sigset_t chldmask, savemask;
struct sigaction ignore, saveint, savequit;
if (!cmdline) {
if (IsWindows()) return 1;
if (!access(_PATH_BSHELL, X_OK)) return 1;
return 0;
}
if (!cmdline) return 1;
ignore.sa_flags = 0;
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);