mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-04-21 14:24:43 +00:00
Reduce memory requirements for execve()
This commit is contained in:
parent
eaca5b3e81
commit
21e1023d28
7 changed files with 35 additions and 32 deletions
|
@ -47,11 +47,8 @@ textwindows int execve$nt(const char *program, char *const argv[],
|
||||||
close(i);
|
close(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; argv[i];) ++i;
|
rc = ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
|
||||||
i = (i + 1) * sizeof(char *);
|
&procinfo);
|
||||||
argv = memcpy(alloca(i), argv, i);
|
|
||||||
memcpy(argv, &program, sizeof(program));
|
|
||||||
rc = ntspawn(argv, envp, NULL, NULL, true, 0, NULL, &startinfo, &procinfo);
|
|
||||||
if (rc == -1) return -1;
|
if (rc == -1) return -1;
|
||||||
CloseHandle(procinfo.hThread);
|
CloseHandle(procinfo.hThread);
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -25,15 +25,16 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
int execve$sysv(const char *prog, char *const argv[], char *const envp[]) {
|
int execve$sysv(const char *prog, char *const argv[], char *const envp[]) {
|
||||||
size_t i, n;
|
size_t i;
|
||||||
char **shargs, bash[PATH_MAX];
|
char **shargs;
|
||||||
if (__execve$sysv(prog, argv, envp) != -1) return 0;
|
if (__execve$sysv(prog, argv, envp) != -1) return 0;
|
||||||
if (errno != ENOEXEC) return -1;
|
if (errno != ENOEXEC) return -1;
|
||||||
for (i = 0; argv[i];) ++i;
|
for (i = 0; argv[i];) ++i;
|
||||||
shargs = alloca((i + 2) * sizeof(char *));
|
shargs = alloca((i + 2) * sizeof(char *));
|
||||||
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
||||||
shargs[0] = !IsFreebsd() ? _PATH_BSHELL
|
shargs[0] = !IsFreebsd() ? _PATH_BSHELL
|
||||||
: firstnonnull(commandv("bash", bash), _PATH_BSHELL);
|
: firstnonnull(commandv("bash", alloca(PATH_MAX)),
|
||||||
|
_PATH_BSHELL);
|
||||||
shargs[1] = prog;
|
shargs[1] = prog;
|
||||||
return __execve$sysv(shargs[0], shargs, envp);
|
return __execve$sysv(shargs[0], shargs, envp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,8 @@ textwindows int fork$nt(void) {
|
||||||
startinfo.hStdInput = g_fds.p[0].handle;
|
startinfo.hStdInput = g_fds.p[0].handle;
|
||||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||||
startinfo.hStdError = g_fds.p[2].handle;
|
startinfo.hStdError = g_fds.p[2].handle;
|
||||||
if (ntspawn(g_argv, environ, &kNtIsInheritable, NULL, true, 0, NULL,
|
if (ntspawn(g_argv[0], g_argv, environ, &kNtIsInheritable, NULL, true, 0,
|
||||||
&startinfo, &procinfo) != -1) {
|
NULL, &startinfo, &procinfo) != -1) {
|
||||||
CloseHandle(reader);
|
CloseHandle(reader);
|
||||||
CloseHandle(procinfo.hThread);
|
CloseHandle(procinfo.hThread);
|
||||||
if (weaken(__sighandrvas) &&
|
if (weaken(__sighandrvas) &&
|
||||||
|
|
|
@ -30,24 +30,28 @@
|
||||||
* GetDosArgv() or GetDosArgv(). This function does NOT escape
|
* GetDosArgv() or GetDosArgv(). This function does NOT escape
|
||||||
* command interpreter syntax, e.g. $VAR (sh), %VAR% (cmd).
|
* command interpreter syntax, e.g. $VAR (sh), %VAR% (cmd).
|
||||||
*
|
*
|
||||||
|
* @param cmdline is output buffer
|
||||||
|
* @param prog is used as argv[0]
|
||||||
* @param argv is an a NULL-terminated array of UTF-8 strings
|
* @param argv is an a NULL-terminated array of UTF-8 strings
|
||||||
* @return freshly allocated lpCommandLine or NULL w/ errno
|
* @return freshly allocated lpCommandLine or NULL w/ errno
|
||||||
* @kudos Daniel Colascione for teaching how to quote
|
* @kudos Daniel Colascione for teaching how to quote
|
||||||
* @see libc/runtime/dosargv.c
|
* @see libc/runtime/dosargv.c
|
||||||
*/
|
*/
|
||||||
textwindows int mkntcmdline(char16_t cmdline[ARG_MAX], char *const argv[]) {
|
textwindows int mkntcmdline(char16_t cmdline[ARG_MAX], const char *prog,
|
||||||
|
char *const argv[]) {
|
||||||
|
char *arg;
|
||||||
uint64_t w;
|
uint64_t w;
|
||||||
wint_t x, y;
|
wint_t x, y;
|
||||||
int slashes, n;
|
int slashes, n;
|
||||||
size_t i, j, k;
|
size_t i, j, k;
|
||||||
bool needsquote;
|
bool needsquote;
|
||||||
char16_t cbuf[2];
|
char16_t cbuf[2];
|
||||||
for (k = i = 0; argv[i]; ++i) {
|
for (arg = prog, k = i = 0; arg; arg = argv[++i]) {
|
||||||
if (i) {
|
if (i) {
|
||||||
cmdline[k++] = u' ';
|
cmdline[k++] = u' ';
|
||||||
if (k == ARG_MAX) return e2big();
|
if (k == ARG_MAX) return e2big();
|
||||||
}
|
}
|
||||||
needsquote = !*argv[i] || argv[i][strcspn(argv[i], " \t\n\v\"")];
|
needsquote = !arg[0] || arg[strcspn(arg, " \t\n\v\"")];
|
||||||
if (needsquote) {
|
if (needsquote) {
|
||||||
cmdline[k++] = u'"';
|
cmdline[k++] = u'"';
|
||||||
if (k == ARG_MAX) return e2big();
|
if (k == ARG_MAX) return e2big();
|
||||||
|
@ -55,20 +59,20 @@ textwindows int mkntcmdline(char16_t cmdline[ARG_MAX], char *const argv[]) {
|
||||||
for (j = 0;;) {
|
for (j = 0;;) {
|
||||||
if (needsquote) {
|
if (needsquote) {
|
||||||
slashes = 0;
|
slashes = 0;
|
||||||
while (argv[i][j] && argv[i][j] == '\\') slashes++, j++;
|
while (arg[j] && arg[j] == '\\') slashes++, j++;
|
||||||
slashes <<= 1;
|
slashes <<= 1;
|
||||||
if (argv[i][j] == '"') slashes++;
|
if (arg[j] == '"') slashes++;
|
||||||
while (slashes--) {
|
while (slashes--) {
|
||||||
cmdline[k++] = u'\\';
|
cmdline[k++] = u'\\';
|
||||||
if (k == ARG_MAX) return e2big();
|
if (k == ARG_MAX) return e2big();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x = argv[i][j++] & 0xff;
|
x = arg[j++] & 0xff;
|
||||||
if (x >= 0300) {
|
if (x >= 0300) {
|
||||||
n = ThomPikeLen(x);
|
n = ThomPikeLen(x);
|
||||||
x = ThomPikeByte(x);
|
x = ThomPikeByte(x);
|
||||||
while (--n) {
|
while (--n) {
|
||||||
if ((y = argv[i][j++] & 0xff)) {
|
if ((y = arg[j++] & 0xff)) {
|
||||||
x = ThomPikeMerge(x, y);
|
x = ThomPikeMerge(x, y);
|
||||||
} else {
|
} else {
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
|
@ -58,7 +58,7 @@ struct SpawnBlock {
|
||||||
* @see spawnve() which abstracts this function
|
* @see spawnve() which abstracts this function
|
||||||
*/
|
*/
|
||||||
textwindows int ntspawn(
|
textwindows int ntspawn(
|
||||||
char *const argv[], char *const envp[],
|
const char *prog, char *const argv[], char *const envp[],
|
||||||
struct NtSecurityAttributes *opt_lpProcessAttributes,
|
struct NtSecurityAttributes *opt_lpProcessAttributes,
|
||||||
struct NtSecurityAttributes *opt_lpThreadAttributes, bool32 bInheritHandles,
|
struct NtSecurityAttributes *opt_lpThreadAttributes, bool32 bInheritHandles,
|
||||||
uint32_t dwCreationFlags, const char16_t *opt_lpCurrentDirectory,
|
uint32_t dwCreationFlags, const char16_t *opt_lpCurrentDirectory,
|
||||||
|
@ -80,7 +80,7 @@ textwindows int ntspawn(
|
||||||
(block =
|
(block =
|
||||||
MapViewOfFileExNuma(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0,
|
MapViewOfFileExNuma(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0,
|
||||||
blocksize, NULL, kNtNumaNoPreferredNode))) {
|
blocksize, NULL, kNtNumaNoPreferredNode))) {
|
||||||
if (mkntcmdline(block->cmdline, argv) != -1 &&
|
if (mkntcmdline(block->cmdline, prog, argv) != -1 &&
|
||||||
mkntenvblock(block->envvars, envp) != -1) {
|
mkntenvblock(block->envvars, envp) != -1) {
|
||||||
if (CreateProcess(NULL, block->cmdline, opt_lpProcessAttributes,
|
if (CreateProcess(NULL, block->cmdline, opt_lpProcessAttributes,
|
||||||
opt_lpThreadAttributes, bInheritHandles,
|
opt_lpThreadAttributes, bInheritHandles,
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
int mkntcmdline(char16_t[ARG_MAX], char *const[]) hidden;
|
int mkntcmdline(char16_t[ARG_MAX], const char *, char *const[]) hidden;
|
||||||
int mkntenvblock(char16_t[ARG_MAX], char *const[]) hidden;
|
int mkntenvblock(char16_t[ARG_MAX], char *const[]) hidden;
|
||||||
int ntspawn(char *const[], char *const[], struct NtSecurityAttributes *,
|
int ntspawn(const char *, char *const[], char *const[],
|
||||||
struct NtSecurityAttributes *, bool32, uint32_t, const char16_t *,
|
struct NtSecurityAttributes *, struct NtSecurityAttributes *,
|
||||||
const struct NtStartupInfo *, struct NtProcessInformation *) hidden;
|
bool32, uint32_t, const char16_t *, const struct NtStartupInfo *,
|
||||||
|
struct NtProcessInformation *) hidden;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -27,49 +27,49 @@ char16_t cmdline[ARG_MAX];
|
||||||
|
|
||||||
TEST(mkntcmdline, emptyArgvList_isEmpty) {
|
TEST(mkntcmdline, emptyArgvList_isEmpty) {
|
||||||
char *argv[] = {NULL};
|
char *argv[] = {NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"", cmdline);
|
EXPECT_STREQ(u"", cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mkntcmdline, emptyArg_getsQuoted) {
|
TEST(mkntcmdline, emptyArg_getsQuoted) {
|
||||||
char *argv[] = {"", NULL};
|
char *argv[] = {"", NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"\"\"", cmdline);
|
EXPECT_STREQ(u"\"\"", cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mkntcmdline, ignoranceIsBliss) {
|
TEST(mkntcmdline, ignoranceIsBliss) {
|
||||||
char *argv[] = {"echo", "hello", "world", NULL};
|
char *argv[] = {"echo", "hello", "world", NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"echo hello world", cmdline);
|
EXPECT_STREQ(u"echo hello world", cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mkntcmdline, spaceInArgument_getQuotesWrappedAround) {
|
TEST(mkntcmdline, spaceInArgument_getQuotesWrappedAround) {
|
||||||
char *argv[] = {"echo", "hello there", "world", NULL};
|
char *argv[] = {"echo", "hello there", "world", NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"echo \"hello there\" world", cmdline);
|
EXPECT_STREQ(u"echo \"hello there\" world", cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mkntcmdline, justQuote) {
|
TEST(mkntcmdline, justQuote) {
|
||||||
char *argv[] = {"\"", NULL};
|
char *argv[] = {"\"", NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"\"\\\"\"", cmdline);
|
EXPECT_STREQ(u"\"\\\"\"", cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mkntcmdline, justSlash) {
|
TEST(mkntcmdline, justSlash) {
|
||||||
char *argv[] = {"\\", NULL};
|
char *argv[] = {"\\", NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"\\", cmdline);
|
EXPECT_STREQ(u"\\", cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mkntcmdline, justSlashQuote) {
|
TEST(mkntcmdline, justSlashQuote) {
|
||||||
char *argv[] = {"\\\"", NULL};
|
char *argv[] = {"\\\"", NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"\"\\\\\\\"\"" /* "\\\"" */, cmdline);
|
EXPECT_STREQ(u"\"\\\\\\\"\"" /* "\\\"" */, cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(mkntcmdline, basicQuoting) {
|
TEST(mkntcmdline, basicQuoting) {
|
||||||
char *argv[] = {"a\"b c", "d", NULL};
|
char *argv[] = {"a\"b c", "d", NULL};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv));
|
||||||
EXPECT_STREQ(u"\"a\\\"b c\" d" /* "a\"b c" d */, cmdline);
|
EXPECT_STREQ(u"\"a\\\"b c\" d" /* "a\"b c" d */, cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ TEST(mkntcmdline, testUnicode) {
|
||||||
strdup("要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非"),
|
strdup("要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非"),
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv1));
|
EXPECT_NE(-1, mkntcmdline(cmdline, argv1[0], argv1));
|
||||||
EXPECT_STREQ(u"(╯°□°)╯ \"要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非\"",
|
EXPECT_STREQ(u"(╯°□°)╯ \"要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非\"",
|
||||||
cmdline);
|
cmdline);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue