mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-02 17:28:30 +00:00
Make improvements
- You can now run `make -j8 toolchain` on Windows - You can now run `make -j` on MacOS ARM64 and BSD OSes - You can now use our Emacs dev environment on MacOS/Windows - Fix bug where the x16 register was being corrupted by --ftrace - The programs under build/bootstrap/ are updated as fat binaries - The Makefile now explains how to download cosmocc-0.0.12 toolchain - The build scripts under bin/ now support "cosmo" branded toolchains - stat() now goes faster on Windows (shaves 100ms off `make` latency) - Code cleanup and added review on the Windows signal checking code - posix_spawnattr_setrlimit() now works around MacOS ARM64 bugs - Landlock Make now favors posix_spawn() on non-Linux/OpenBSD - posix_spawn() now has better --strace logging on Windows - fstatat() can now avoid EACCES in more cases on Windows - fchmod() can now change the readonly bit on Windows
This commit is contained in:
parent
06c6baaf50
commit
c9fecf3a55
109 changed files with 1188 additions and 454 deletions
6
third_party/make/config.h
vendored
6
third_party/make/config.h
vendored
|
@ -286,12 +286,6 @@
|
|||
/* Define to 1 if you have the `pipe' function. */
|
||||
#define HAVE_PIPE 1
|
||||
|
||||
/* Define to 1 if you have the `posix_spawn' function. */
|
||||
#define HAVE_POSIX_SPAWN 1
|
||||
|
||||
/* Define to 1 if you have the `posix_spawnattr_setsigmask' function. */
|
||||
#define HAVE_POSIX_SPAWNATTR_SETSIGMASK 1
|
||||
|
||||
/* Define to 1 if you have the `pselect' function. */
|
||||
#define HAVE_PSELECT 1
|
||||
|
||||
|
|
2
third_party/make/dirname.h
vendored
2
third_party/make/dirname.h
vendored
|
@ -20,7 +20,7 @@
|
|||
|
||||
#ifndef DIRNAME_H_
|
||||
# define DIRNAME_H_ 1
|
||||
#include "third_party/make/dosname.h"
|
||||
#include "third_party/make/filename.h"
|
||||
|
||||
# ifndef DIRECTORY_SEPARATOR
|
||||
# define DIRECTORY_SEPARATOR '/'
|
||||
|
|
53
third_party/make/dosname.h
vendored
53
third_party/make/dosname.h
vendored
|
@ -1,53 +0,0 @@
|
|||
/* clang-format off */
|
||||
/* File names on MS-DOS/Windows systems.
|
||||
|
||||
Copyright (C) 2000-2001, 2004-2006, 2009-2020 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
From Paul Eggert and Jim Meyering. */
|
||||
|
||||
#ifndef _DOSNAME_H
|
||||
#define _DOSNAME_H
|
||||
|
||||
#if (defined _WIN32 || defined __CYGWIN__ \
|
||||
|| defined __EMX__ || defined __MSDOS__ || defined __DJGPP__)
|
||||
/* This internal macro assumes ASCII, but all hosts that support drive
|
||||
letters use ASCII. */
|
||||
# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
|
||||
<= 'z' - 'a')
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) \
|
||||
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
|
||||
# ifndef __CYGWIN__
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
|
||||
# endif
|
||||
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
|
||||
#else
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# define ISSLASH(C) ((C) == '/')
|
||||
#endif
|
||||
|
||||
#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
|
||||
#endif
|
||||
|
||||
#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
|
||||
# else
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) \
|
||||
(ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
|
||||
#endif
|
||||
#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
|
||||
|
||||
#endif /* DOSNAME_H_ */
|
22
third_party/make/filename.h
vendored
22
third_party/make/filename.h
vendored
|
@ -29,23 +29,13 @@ extern "C" {
|
|||
it may be concatenated to a directory pathname.
|
||||
IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
|
||||
*/
|
||||
#if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
|
||||
/* Native Windows, Cygwin, OS/2, DOS */
|
||||
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
|
||||
# define HAS_DEVICE(P) \
|
||||
((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
|
||||
&& (P)[1] == ':')
|
||||
# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
|
||||
# define IS_PATH_WITH_DIR(P) \
|
||||
(strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
|
||||
# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
|
||||
#else
|
||||
/* Unix */
|
||||
# define ISSLASH(C) ((C) == '/')
|
||||
# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
|
||||
# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
|
||||
# define FILE_SYSTEM_PREFIX_LEN(P) 0
|
||||
#endif
|
||||
# define HAS_DEVICE(Filename) ((void) (Filename), 0)
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0)
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
|
||||
# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0])
|
||||
# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0]))
|
||||
# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
217
third_party/make/findprog-in.c
vendored
217
third_party/make/findprog-in.c
vendored
|
@ -20,6 +20,9 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "third_party/make/filename.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "third_party/make/config.h"
|
||||
|
||||
/* Specification. */
|
||||
|
@ -58,8 +61,8 @@ static const char * const suffixes[] =
|
|||
/* Note: The cmd.exe program does a different lookup: It searches according
|
||||
to the PATHEXT environment variable.
|
||||
See <https://stackoverflow.com/questions/7839150/>.
|
||||
Also, it executes files ending .bat and .cmd directly without letting the
|
||||
kernel interpret the program file. */
|
||||
Also, it executes files ending in .bat and .cmd directly without letting
|
||||
the kernel interpret the program file. */
|
||||
#elif defined __CYGWIN__
|
||||
"", ".exe", ".com"
|
||||
#elif defined __EMX__
|
||||
|
@ -73,7 +76,7 @@ static const char * const suffixes[] =
|
|||
|
||||
const char *
|
||||
find_in_given_path (const char *progname, const char *path,
|
||||
bool optimize_for_exec)
|
||||
const char *directory, bool optimize_for_exec)
|
||||
{
|
||||
{
|
||||
bool has_slash = false;
|
||||
|
@ -101,6 +104,12 @@ find_in_given_path (const char *progname, const char *path,
|
|||
with such a suffix is actually executable. */
|
||||
int failure_errno;
|
||||
size_t i;
|
||||
|
||||
const char *directory_as_prefix =
|
||||
(directory != NULL && IS_RELATIVE_FILE_NAME (progname)
|
||||
? directory
|
||||
: "");
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
const char *progbasename;
|
||||
|
||||
|
@ -112,6 +121,8 @@ find_in_given_path (const char *progname, const char *path,
|
|||
if (ISSLASH (*p))
|
||||
progbasename = p + 1;
|
||||
}
|
||||
|
||||
bool progbasename_has_dot = (strchr (progbasename, '.') != NULL);
|
||||
#endif
|
||||
|
||||
/* Try all platform-dependent suffixes. */
|
||||
|
@ -123,12 +134,16 @@ find_in_given_path (const char *progname, const char *path,
|
|||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
/* File names without a '.' are not considered executable, and
|
||||
for file names with a '.' no additional suffix is tried. */
|
||||
if ((*suffix != '\0') != (strchr (progbasename, '.') != NULL))
|
||||
if ((*suffix != '\0') != progbasename_has_dot)
|
||||
#endif
|
||||
{
|
||||
/* Concatenate progname and suffix. */
|
||||
/* Concatenate directory_as_prefix, progname, suffix. */
|
||||
char *progpathname =
|
||||
xconcatenated_filename ("", progname, suffix);
|
||||
concatenated_filename (directory_as_prefix, progname,
|
||||
suffix);
|
||||
|
||||
if (progpathname == NULL)
|
||||
return NULL; /* errno is set here */
|
||||
|
||||
/* On systems which have the eaccess() system call, let's
|
||||
use it. On other systems, let's hope that this program
|
||||
|
@ -136,14 +151,26 @@ find_in_given_path (const char *progname, const char *path,
|
|||
call access() despite its design flaw. */
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
/* Check that the progpathname does not point to a
|
||||
directory. */
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
free (progpathname);
|
||||
return progname;
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
{
|
||||
free (progpathname);
|
||||
return progname;
|
||||
}
|
||||
else
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
errno = EACCES;
|
||||
}
|
||||
else
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
|
@ -152,6 +179,36 @@ find_in_given_path (const char *progname, const char *path,
|
|||
free (progpathname);
|
||||
}
|
||||
}
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
if (failure_errno == ENOENT && !progbasename_has_dot)
|
||||
{
|
||||
/* In the loop above, we skipped suffix = "". Do this loop
|
||||
round now, merely to provide a better errno than ENOENT. */
|
||||
|
||||
char *progpathname =
|
||||
concatenated_filename (directory_as_prefix, progname, "");
|
||||
|
||||
if (progpathname == NULL)
|
||||
return NULL; /* errno is set here */
|
||||
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
errno = ENOEXEC;
|
||||
else
|
||||
errno = EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
failure_errno = errno;
|
||||
|
||||
free (progpathname);
|
||||
}
|
||||
#endif
|
||||
|
||||
errno = failure_errno;
|
||||
return NULL;
|
||||
|
@ -165,17 +222,26 @@ find_in_given_path (const char *progname, const char *path,
|
|||
path = "";
|
||||
|
||||
{
|
||||
int failure_errno;
|
||||
/* Make a copy, to prepare for destructive modifications. */
|
||||
char *path_copy = xstrdup (path);
|
||||
char *path_copy = strdup (path);
|
||||
if (path_copy == NULL)
|
||||
return NULL; /* errno is set here */
|
||||
|
||||
int failure_errno;
|
||||
char *path_rest;
|
||||
char *cp;
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
bool progname_has_dot = (strchr (progname, '.') != NULL);
|
||||
#endif
|
||||
|
||||
failure_errno = ENOENT;
|
||||
for (path_rest = path_copy; ; path_rest = cp + 1)
|
||||
{
|
||||
const char *dir;
|
||||
bool last;
|
||||
char *dir_as_prefix_to_free;
|
||||
const char *dir_as_prefix;
|
||||
size_t i;
|
||||
|
||||
/* Extract next directory in PATH. */
|
||||
|
@ -189,6 +255,25 @@ find_in_given_path (const char *progname, const char *path,
|
|||
if (dir == cp)
|
||||
dir = ".";
|
||||
|
||||
/* Concatenate directory and dir. */
|
||||
if (directory != NULL && IS_RELATIVE_FILE_NAME (dir))
|
||||
{
|
||||
dir_as_prefix_to_free =
|
||||
concatenated_filename (directory, dir, NULL);
|
||||
if (dir_as_prefix_to_free == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
goto failed;
|
||||
}
|
||||
dir_as_prefix = dir_as_prefix_to_free;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir_as_prefix_to_free = NULL;
|
||||
dir_as_prefix = dir;
|
||||
}
|
||||
|
||||
/* Try all platform-dependent suffixes. */
|
||||
for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++)
|
||||
{
|
||||
|
@ -197,12 +282,20 @@ find_in_given_path (const char *progname, const char *path,
|
|||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
/* File names without a '.' are not considered executable, and
|
||||
for file names with a '.' no additional suffix is tried. */
|
||||
if ((*suffix != '\0') != (strchr (progname, '.') != NULL))
|
||||
if ((*suffix != '\0') != progname_has_dot)
|
||||
#endif
|
||||
{
|
||||
/* Concatenate dir, progname, and suffix. */
|
||||
/* Concatenate dir_as_prefix, progname, and suffix. */
|
||||
char *progpathname =
|
||||
xconcatenated_filename (dir, progname, suffix);
|
||||
concatenated_filename (dir_as_prefix, progname, suffix);
|
||||
|
||||
if (progpathname == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
free (dir_as_prefix_to_free);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* On systems which have the eaccess() system call, let's
|
||||
use it. On other systems, let's hope that this program
|
||||
|
@ -210,25 +303,45 @@ find_in_given_path (const char *progname, const char *path,
|
|||
call access() despite its design flaw. */
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
/* Check that the progpathname does not point to a
|
||||
directory. */
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
free (progpathname);
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
{
|
||||
free (progpathname);
|
||||
|
||||
/* Add the "./" prefix for real, that
|
||||
xconcatenated_filename() optimized away. This
|
||||
avoids a second PATH search when the caller uses
|
||||
execl/execv/execlp/execvp. */
|
||||
progpathname =
|
||||
XNMALLOC (2 + strlen (progname) + 1, char);
|
||||
progpathname[0] = '.';
|
||||
progpathname[1] = NATIVE_SLASH;
|
||||
memcpy (progpathname + 2, progname,
|
||||
strlen (progname) + 1);
|
||||
/* Add the "./" prefix for real, that
|
||||
concatenated_filename() optimized away.
|
||||
This avoids a second PATH search when the
|
||||
caller uses execl/execv/execlp/execvp. */
|
||||
progpathname =
|
||||
(char *) malloc (2 + strlen (progname) + 1);
|
||||
if (progpathname == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
free (dir_as_prefix_to_free);
|
||||
goto failed;
|
||||
}
|
||||
progpathname[0] = '.';
|
||||
progpathname[1] = NATIVE_SLASH;
|
||||
memcpy (progpathname + 2, progname,
|
||||
strlen (progname) + 1);
|
||||
}
|
||||
|
||||
free (dir_as_prefix_to_free);
|
||||
free (path_copy);
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
errno = EACCES;
|
||||
}
|
||||
|
||||
free (path_copy);
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
|
@ -237,11 +350,49 @@ find_in_given_path (const char *progname, const char *path,
|
|||
free (progpathname);
|
||||
}
|
||||
}
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
if (failure_errno == ENOENT && !progname_has_dot)
|
||||
{
|
||||
/* In the loop above, we skipped suffix = "". Do this loop
|
||||
round now, merely to provide a better errno than ENOENT. */
|
||||
|
||||
char *progpathname =
|
||||
concatenated_filename (dir_as_prefix, progname, "");
|
||||
|
||||
if (progpathname == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
free (dir_as_prefix_to_free);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
errno = ENOEXEC;
|
||||
else
|
||||
errno = EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
failure_errno = errno;
|
||||
|
||||
free (progpathname);
|
||||
}
|
||||
#endif
|
||||
|
||||
free (dir_as_prefix_to_free);
|
||||
|
||||
if (last)
|
||||
break;
|
||||
}
|
||||
|
||||
failed:
|
||||
/* Not found in PATH. */
|
||||
free (path_copy);
|
||||
|
||||
|
|
6
third_party/make/findprog.h
vendored
6
third_party/make/findprog.h
vendored
|
@ -41,6 +41,10 @@ extern const char *find_in_path (const char *progname);
|
|||
directory. A null PATH is equivalent to an empty PATH, that is, to the
|
||||
singleton list that contains only the current directory.
|
||||
|
||||
If DIRECTORY is not NULL, all relative filenames (i.e. PROGNAME when it
|
||||
contains a slash, and the PATH elements) are considered relative to
|
||||
DIRECTORY instead of relative to the current directory of this process.
|
||||
|
||||
Determines the pathname that would be called by execlp/execvp of PROGNAME.
|
||||
- If successful, it returns a pathname containing a slash (either absolute
|
||||
or relative to the current directory). The returned string can be used
|
||||
|
@ -52,6 +56,7 @@ extern const char *find_in_path (const char *progname);
|
|||
- EACCES: means that the program's file cannot be accessed (due to some
|
||||
issue with one of the ancestor directories) or lacks the execute
|
||||
permissions.
|
||||
- ENOMEM: means out of memory.
|
||||
If OPTIMIZE_FOR_EXEC is true, the function saves some work, under the
|
||||
assumption that the resulting pathname will not be accessed directly,
|
||||
only through execl/execv or execlp/execvp.
|
||||
|
@ -60,6 +65,7 @@ extern const char *find_in_path (const char *progname);
|
|||
- On POSIX systems excluding Cygwin: a '/',
|
||||
- On Windows, OS/2, DOS platforms: a '/' or '\'. */
|
||||
extern const char *find_in_given_path (const char *progname, const char *path,
|
||||
const char *directory,
|
||||
bool optimize_for_exec);
|
||||
|
||||
|
||||
|
|
195
third_party/make/job.c
vendored
195
third_party/make/job.c
vendored
|
@ -47,6 +47,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nexgen32e/kcpuids.h"
|
||||
#include "libc/proc/posix_spawn.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -63,10 +64,14 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "libc/x/x.h"
|
||||
#include "third_party/make/commands.h"
|
||||
#include "third_party/make/dep.h"
|
||||
#include "third_party/make/findprog.h"
|
||||
#include "third_party/make/os.h"
|
||||
#include "third_party/make/variable.h"
|
||||
// clang-format off
|
||||
|
||||
#define USE_POSIX_SPAWN (!IsLinux() && !IsOpenbsd())
|
||||
#define HAVE_POSIX_SPAWNATTR_SETSIGMASK
|
||||
|
||||
#ifdef WINDOWS32
|
||||
const char *default_shell = "sh.exe";
|
||||
int no_default_sh_exe = 1;
|
||||
|
@ -1891,6 +1896,153 @@ child_execute_job (struct childbase *child,
|
|||
fderr = child->output.err;
|
||||
}
|
||||
|
||||
if (USE_POSIX_SPAWN) {
|
||||
char *cmd;
|
||||
posix_spawnattr_t attr;
|
||||
posix_spawn_file_actions_t fa;
|
||||
short flags = 0;
|
||||
|
||||
if ((r = posix_spawnattr_init (&attr)) != 0)
|
||||
goto done;
|
||||
|
||||
if ((r = posix_spawn_file_actions_init (&fa)) != 0)
|
||||
{
|
||||
posix_spawnattr_destroy (&attr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
// [jart] use setrlimit on posix_spawn
|
||||
// TODO(jart): support landlock make rlimit variables
|
||||
if (stack_limit.rlim_cur && RLIMIT_STACK < RLIM_NLIMITS)
|
||||
{
|
||||
posix_spawnattr_setrlimit (&attr, RLIMIT_STACK, &stack_limit);
|
||||
flags |= POSIX_SPAWN_SETRLIMIT;
|
||||
}
|
||||
|
||||
/* Unblock all signals. */
|
||||
#ifdef HAVE_POSIX_SPAWNATTR_SETSIGMASK
|
||||
{
|
||||
sigset_t mask;
|
||||
sigemptyset (&mask);
|
||||
r = posix_spawnattr_setsigmask (&attr, &mask);
|
||||
if (r != 0)
|
||||
goto cleanup;
|
||||
flags |= POSIX_SPAWN_SETSIGMASK;
|
||||
}
|
||||
#endif /* have posix_spawnattr_setsigmask() */
|
||||
|
||||
/* USEVFORK can give significant speedup on systems where it's available. */
|
||||
#ifdef POSIX_SPAWN_USEVFORK
|
||||
flags |= POSIX_SPAWN_USEVFORK;
|
||||
#endif
|
||||
|
||||
/* For any redirected FD, dup2() it to the standard FD.
|
||||
They are all marked close-on-exec already. */
|
||||
if (fdin >= 0 && fdin != FD_STDIN)
|
||||
if ((r = posix_spawn_file_actions_adddup2 (&fa, fdin, FD_STDIN)) != 0)
|
||||
goto cleanup;
|
||||
if (fdout != FD_STDOUT)
|
||||
if ((r = posix_spawn_file_actions_adddup2 (&fa, fdout, FD_STDOUT)) != 0)
|
||||
goto cleanup;
|
||||
if (fderr != FD_STDERR)
|
||||
if ((r = posix_spawn_file_actions_adddup2 (&fa, fderr, FD_STDERR)) != 0)
|
||||
goto cleanup;
|
||||
|
||||
/* We can't use the POSIX_SPAWN_RESETIDS flag: when make is invoked under
|
||||
restrictive environments like unshare it will fail with EINVAL. */
|
||||
|
||||
/* Apply the spawn flags. */
|
||||
if ((r = posix_spawnattr_setflags (&attr, flags)) != 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Look up the program on the child's PATH, if needed. */
|
||||
{
|
||||
const char *p = NULL;
|
||||
char **pp;
|
||||
|
||||
for (pp = child->environment; *pp != NULL; ++pp)
|
||||
if ((*pp)[0] == 'P' && (*pp)[1] == 'A' && (*pp)[2] == 'T'
|
||||
&& (*pp)[3] == 'H' &&(*pp)[4] == '=')
|
||||
{
|
||||
p = (*pp) + 5;
|
||||
break;
|
||||
}
|
||||
|
||||
/* execvp() will use a default PATH if none is set; emulate that. */
|
||||
if (p == NULL)
|
||||
{
|
||||
size_t l = confstr (_CS_PATH, NULL, 0);
|
||||
if (l)
|
||||
{
|
||||
char *dp = alloca (l);
|
||||
confstr (_CS_PATH, dp, l);
|
||||
p = dp;
|
||||
}
|
||||
}
|
||||
|
||||
cmd = (char *)find_in_given_path (argv[0], p, NULL, 0);
|
||||
}
|
||||
|
||||
if (!cmd)
|
||||
{
|
||||
r = errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Start the program. */
|
||||
while ((r = posix_spawn (&pid, cmd, &fa, &attr, argv,
|
||||
child->environment)) == EINTR)
|
||||
;
|
||||
|
||||
/* posix_spawn() doesn't provide sh fallback like exec() does; implement
|
||||
it here. POSIX doesn't specify the path to sh so use the default. */
|
||||
|
||||
if (r == ENOEXEC)
|
||||
{
|
||||
char **nargv;
|
||||
char **pp;
|
||||
size_t l = 0;
|
||||
|
||||
for (pp = argv; *pp != NULL; ++pp)
|
||||
++l;
|
||||
|
||||
nargv = xmalloc (sizeof (char *) * (l + 3));
|
||||
nargv[0] = (char *)default_shell;
|
||||
nargv[1] = cmd;
|
||||
memcpy (&nargv[2], &argv[1], sizeof (char *) * l);
|
||||
|
||||
while ((r = posix_spawn (&pid, nargv[0], &fa, &attr, nargv,
|
||||
child->environment)) == EINTR)
|
||||
;
|
||||
|
||||
free (nargv);
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
/* Spawn succeeded but may fail later: remember the command. */
|
||||
free (child->cmd_name);
|
||||
if (cmd != argv[0])
|
||||
child->cmd_name = cmd;
|
||||
else
|
||||
child->cmd_name = xstrdup(cmd);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
posix_spawn_file_actions_destroy (&fa);
|
||||
posix_spawnattr_destroy (&attr);
|
||||
|
||||
done:
|
||||
if (r != 0)
|
||||
pid = -1;
|
||||
|
||||
if (pid < 0)
|
||||
OSS (error, NILF, "%s: %s", argv[0], strerror (r));
|
||||
|
||||
return pid;
|
||||
|
||||
} // USE_POSIX_SPAWN
|
||||
|
||||
pid = fork();
|
||||
if (pid != 0)
|
||||
return pid;
|
||||
|
@ -2446,17 +2598,23 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
|
|||
shell = default_shell;
|
||||
|
||||
/* [jart] remove code that forces slow path if not using /bin/sh */
|
||||
/* else if (strcmp (shell, default_shell)) */
|
||||
/* goto slow; */
|
||||
|
||||
if (ifs)
|
||||
for (cap = ifs; *cap != '\0'; ++cap)
|
||||
if (*cap != ' ' && *cap != '\t' && *cap != '\n')
|
||||
if (*cap != ' ' && *cap != '\t' && *cap != '\n') {
|
||||
// kprintf("slow because whitespace\n");
|
||||
goto slow;
|
||||
}
|
||||
|
||||
if (shellflags)
|
||||
if (shellflags[0] != '-'
|
||||
|| ((shellflags[1] != 'c' || shellflags[2] != '\0')
|
||||
&& (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0')))
|
||||
&& (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0'))) {
|
||||
// kprintf("slow because shell flags\n");
|
||||
goto slow;
|
||||
}
|
||||
|
||||
i = strlen (line) + 1;
|
||||
|
||||
|
@ -2515,18 +2673,21 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
|
|||
If we see any of those, punt.
|
||||
But on MSDOS, if we use COMMAND.COM, double and single
|
||||
quotes have the same effect. */
|
||||
else if (instring == '"' && strchr ("\\$`", *p) != 0 && unixy_shell)
|
||||
else if (instring == '"' && strchr ("\\$`", *p) != 0 && unixy_shell) {
|
||||
// kprintf("slow because backslash\n");
|
||||
goto slow;
|
||||
else
|
||||
} else
|
||||
*ap++ = *p;
|
||||
}
|
||||
else if (strchr (sh_chars, *p) != 0)
|
||||
else if (strchr (sh_chars, *p) != 0) {
|
||||
/* Not inside a string, but it's a special char. */
|
||||
// kprintf("slow because %#c found in %#s\n", *p, line);
|
||||
goto slow;
|
||||
else if (one_shell && *p == '\n')
|
||||
} else if (one_shell && *p == '\n') {
|
||||
/* In .ONESHELL mode \n is a separator like ; or && */
|
||||
// kprintf("slow because oneshell thing\n");
|
||||
goto slow;
|
||||
else
|
||||
} else
|
||||
/* Not a special char. */
|
||||
switch (*p)
|
||||
{
|
||||
|
@ -2535,8 +2696,10 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
|
|||
first word with no equals sign in it. This is not the case
|
||||
with sh -k, but we never get here when using nonstandard
|
||||
shell flags. */
|
||||
if (! seen_nonequals && unixy_shell)
|
||||
if (! seen_nonequals && unixy_shell) {
|
||||
// kprintf("slow because nonequals\n");
|
||||
goto slow;
|
||||
}
|
||||
word_has_equals = 1;
|
||||
*ap++ = '=';
|
||||
break;
|
||||
|
@ -2590,10 +2753,12 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
|
|||
/* Update SEEN_NONEQUALS, which tells us if every word
|
||||
heretofore has contained an '='. */
|
||||
seen_nonequals |= ! word_has_equals;
|
||||
if (word_has_equals && ! seen_nonequals)
|
||||
if (word_has_equals && ! seen_nonequals) {
|
||||
/* An '=' in a word before the first
|
||||
word without one is magical. */
|
||||
// kprintf("slow because word equals\n");
|
||||
goto slow;
|
||||
}
|
||||
word_has_equals = 0; /* Prepare for the next word. */
|
||||
|
||||
/* If this argument is the command name,
|
||||
|
@ -2604,8 +2769,10 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
|
|||
int j;
|
||||
for (j = 0; sh_cmds[j] != 0; ++j)
|
||||
{
|
||||
if (streq (sh_cmds[j], new_argv[0]))
|
||||
if (streq (sh_cmds[j], new_argv[0])) {
|
||||
// kprintf("slow because builtin shell commands\n");
|
||||
goto slow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2621,9 +2788,11 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
|
|||
}
|
||||
end_of_line:
|
||||
|
||||
if (instring)
|
||||
if (instring) {
|
||||
/* Let the shell deal with an unterminated quote. */
|
||||
// kprintf("slow because unterminated quote\n");
|
||||
goto slow;
|
||||
}
|
||||
|
||||
/* Terminate the last argument and the argument list. */
|
||||
|
||||
|
@ -2636,8 +2805,10 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
|
|||
{
|
||||
int j;
|
||||
for (j = 0; sh_cmds[j] != 0; ++j)
|
||||
if (streq (sh_cmds[j], new_argv[0]))
|
||||
if (streq (sh_cmds[j], new_argv[0])) {
|
||||
// kprintf("slow because sh_cmds\n");
|
||||
goto slow;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_argv[0] == 0)
|
||||
|
|
8
third_party/make/main.c
vendored
8
third_party/make/main.c
vendored
|
@ -971,7 +971,7 @@ reset_jobserver (void)
|
|||
int
|
||||
main (int argc, char **argv, char **envp)
|
||||
{
|
||||
ShowCrashReports();
|
||||
// ShowCrashReports();
|
||||
|
||||
static char *stdin_nm = 0;
|
||||
int makefile_status = MAKE_SUCCESS;
|
||||
|
@ -982,7 +982,7 @@ main (int argc, char **argv, char **envp)
|
|||
int argv_slots;
|
||||
|
||||
// [jart] workaround to prevent make -j fork bomb
|
||||
default_load_average = __get_cpu_count();
|
||||
default_load_average = __get_cpu_count() * 1.5;
|
||||
max_load_average = default_load_average;
|
||||
|
||||
/* Useful for attaching debuggers, etc. */
|
||||
|
@ -1042,10 +1042,6 @@ main (int argc, char **argv, char **envp)
|
|||
|
||||
#undef FATAL_SIG
|
||||
|
||||
#ifndef NDEBUG
|
||||
ShowCrashReports();
|
||||
#endif
|
||||
|
||||
/* Do not ignore the child-death signal. This must be done before
|
||||
any children could possibly be created; otherwise, the wait
|
||||
functions won't work on systems with the SVR4 ECHILD brain
|
||||
|
|
1
third_party/make/make.mk
vendored
1
third_party/make/make.mk
vendored
|
@ -29,7 +29,6 @@ THIRD_PARTY_MAKE_HDRS = \
|
|||
third_party/make/job.h \
|
||||
third_party/make/unistd.h \
|
||||
third_party/make/getprogname.h \
|
||||
third_party/make/dosname.h \
|
||||
third_party/make/config.h \
|
||||
third_party/make/concat-filename.h \
|
||||
third_party/make/findprog.h \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue