mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-12 01:08:00 +00:00
Handle missing stdio handles on Windows
This commit is contained in:
parent
2227cefa5d
commit
58d22c7c3d
3 changed files with 16 additions and 235 deletions
|
@ -16,10 +16,10 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/intrin/pushpop.h"
|
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/intrin/pthread.h"
|
#include "libc/intrin/pthread.h"
|
||||||
|
#include "libc/intrin/pushpop.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
|
@ -39,6 +39,15 @@ void(__fds_unlock)(void) {
|
||||||
pthread_mutex_unlock(&__fds_lock_obj);
|
pthread_mutex_unlock(&__fds_lock_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) {
|
||||||
|
int64_t h;
|
||||||
|
h = GetStdHandle(x);
|
||||||
|
if (!h || h == -1) return;
|
||||||
|
fds->__init_p[i].kind = pushpop(kFdFile);
|
||||||
|
fds->__init_p[i].handle = h;
|
||||||
|
fds->f = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
textstartup void InitializeFileDescriptors(void) {
|
textstartup void InitializeFileDescriptors(void) {
|
||||||
struct Fds *fds;
|
struct Fds *fds;
|
||||||
fds = VEIL("r", &g_fds);
|
fds = VEIL("r", &g_fds);
|
||||||
|
@ -54,15 +63,10 @@ textstartup void InitializeFileDescriptors(void) {
|
||||||
fds->__init_p[1].handle = VEIL("r", 0x3F8ull);
|
fds->__init_p[1].handle = VEIL("r", 0x3F8ull);
|
||||||
fds->__init_p[2].handle = VEIL("r", 0x3F8ull);
|
fds->__init_p[2].handle = VEIL("r", 0x3F8ull);
|
||||||
} else if (IsWindows()) {
|
} else if (IsWindows()) {
|
||||||
pushmov(&fds->f, 3ull);
|
SetupWinStd(fds, 0, kNtStdInputHandle);
|
||||||
fds->__init_p[0].kind = pushpop(kFdFile);
|
SetupWinStd(fds, 1, kNtStdOutputHandle);
|
||||||
fds->__init_p[1].kind = pushpop(kFdFile);
|
SetupWinStd(fds, 2, kNtStdErrorHandle);
|
||||||
fds->__init_p[2].kind = pushpop(kFdFile);
|
|
||||||
fds->__init_p[0].handle = GetStdHandle(pushpop(kNtStdInputHandle));
|
|
||||||
fds->__init_p[1].handle = GetStdHandle(pushpop(kNtStdOutputHandle));
|
|
||||||
fds->__init_p[2].handle = GetStdHandle(pushpop(kNtStdErrorHandle));
|
|
||||||
}
|
}
|
||||||
fds->__init_p[0].flags = O_RDONLY;
|
|
||||||
fds->__init_p[1].flags = O_WRONLY | O_APPEND;
|
fds->__init_p[1].flags = O_WRONLY | O_APPEND;
|
||||||
fds->__init_p[2].flags = O_WRONLY | O_APPEND;
|
fds->__init_p[2].flags = O_WRONLY | O_APPEND;
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,6 @@ BENCH(clone, bench) {
|
||||||
char *volatile tp;
|
char *volatile tp;
|
||||||
errno_t *volatile ep;
|
errno_t *volatile ep;
|
||||||
EZBENCH2("__errno_location", donothing, (ep = __errno_location()));
|
EZBENCH2("__errno_location", donothing, (ep = __errno_location()));
|
||||||
EZBENCH2("__get_tls_privileged", donothing, (tp = __get_tls_privileged()));
|
EZBENCH2("__get_tls_priv", donothing, (tp = __get_tls_privileged()));
|
||||||
EZBENCH2("__get_tls", donothing, (tp = __get_tls()));
|
EZBENCH2("__get_tls", donothing, (tp = __get_tls()));
|
||||||
}
|
}
|
||||||
|
|
227
third_party/make/function.c
vendored
227
third_party/make/function.c
vendored
|
@ -539,14 +539,6 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
|
||||||
continue;
|
continue;
|
||||||
o = variable_buffer_output (o, p, len - (p - p2));
|
o = variable_buffer_output (o, p, len - (p - p2));
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DOS_PATHS
|
|
||||||
/* Handle the case of "d:foo/bar". */
|
|
||||||
else if (is_notdir && p2[0] && p2[1] == ':')
|
|
||||||
{
|
|
||||||
p = p2 + 2;
|
|
||||||
o = variable_buffer_output (o, p, len - (p - p2));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (is_notdir)
|
else if (is_notdir)
|
||||||
o = variable_buffer_output (o, p2, len);
|
o = variable_buffer_output (o, p2, len);
|
||||||
|
|
||||||
|
@ -587,11 +579,6 @@ func_basename_dir (char *o, char **argv, const char *funcname)
|
||||||
o = variable_buffer_output (o, p2, ++p - p2);
|
o = variable_buffer_output (o, p2, ++p - p2);
|
||||||
else if (p >= p2 && (*p == '.'))
|
else if (p >= p2 && (*p == '.'))
|
||||||
o = variable_buffer_output (o, p2, p - p2);
|
o = variable_buffer_output (o, p2, p - p2);
|
||||||
#ifdef HAVE_DOS_PATHS
|
|
||||||
/* Handle the "d:foobar" case */
|
|
||||||
else if (p2[0] && p2[1] == ':' && is_dir)
|
|
||||||
o = variable_buffer_output (o, p2, 2);
|
|
||||||
#endif
|
|
||||||
else if (is_dir)
|
else if (is_dir)
|
||||||
o = variable_buffer_output (o, "./", 2);
|
o = variable_buffer_output (o, "./", 2);
|
||||||
else
|
else
|
||||||
|
@ -1458,140 +1445,6 @@ shell_completed (int exit_code, int exit_sig)
|
||||||
define_variable_cname (".SHELLSTATUS", buf, o_override, 0);
|
define_variable_cname (".SHELLSTATUS", buf, o_override, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
|
||||||
/*untested*/
|
|
||||||
|
|
||||||
// #include "sub_proc.h"
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv, char **envp)
|
|
||||||
{
|
|
||||||
SECURITY_ATTRIBUTES saAttr;
|
|
||||||
HANDLE hIn = INVALID_HANDLE_VALUE;
|
|
||||||
HANDLE hErr = INVALID_HANDLE_VALUE;
|
|
||||||
HANDLE hChildOutRd;
|
|
||||||
HANDLE hChildOutWr;
|
|
||||||
HANDLE hProcess, tmpIn, tmpErr;
|
|
||||||
DWORD e;
|
|
||||||
|
|
||||||
/* Set status for return. */
|
|
||||||
pipedes[0] = pipedes[1] = -1;
|
|
||||||
*pid_p = (pid_t)-1;
|
|
||||||
|
|
||||||
saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
|
|
||||||
saAttr.bInheritHandle = TRUE;
|
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
|
||||||
|
|
||||||
/* Standard handles returned by GetStdHandle can be NULL or
|
|
||||||
INVALID_HANDLE_VALUE if the parent process closed them. If that
|
|
||||||
happens, we open the null device and pass its handle to
|
|
||||||
process_begin below as the corresponding handle to inherit. */
|
|
||||||
tmpIn = GetStdHandle (STD_INPUT_HANDLE);
|
|
||||||
if (DuplicateHandle (GetCurrentProcess (), tmpIn,
|
|
||||||
GetCurrentProcess (), &hIn,
|
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
|
||||||
{
|
|
||||||
e = GetLastError ();
|
|
||||||
if (e == ERROR_INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
tmpIn = CreateFile ("NUL", GENERIC_READ,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (tmpIn != INVALID_HANDLE_VALUE
|
|
||||||
&& DuplicateHandle (GetCurrentProcess (), tmpIn,
|
|
||||||
GetCurrentProcess (), &hIn,
|
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
|
||||||
CloseHandle (tmpIn);
|
|
||||||
}
|
|
||||||
if (hIn == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
ON (error, NILF,
|
|
||||||
_("windows32_openpipe: DuplicateHandle(In) failed (e=%ld)\n"), e);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmpErr = (HANDLE)_get_osfhandle (errfd);
|
|
||||||
if (DuplicateHandle (GetCurrentProcess (), tmpErr,
|
|
||||||
GetCurrentProcess (), &hErr,
|
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
|
||||||
{
|
|
||||||
e = GetLastError ();
|
|
||||||
if (e == ERROR_INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
tmpErr = CreateFile ("NUL", GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (tmpErr != INVALID_HANDLE_VALUE
|
|
||||||
&& DuplicateHandle (GetCurrentProcess (), tmpErr,
|
|
||||||
GetCurrentProcess (), &hErr,
|
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
|
||||||
CloseHandle (tmpErr);
|
|
||||||
}
|
|
||||||
if (hErr == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
ON (error, NILF,
|
|
||||||
_("windows32_openpipe: DuplicateHandle(Err) failed (e=%ld)\n"), e);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0))
|
|
||||||
{
|
|
||||||
ON (error, NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
hProcess = process_init_fd (hIn, hChildOutWr, hErr);
|
|
||||||
|
|
||||||
if (!hProcess)
|
|
||||||
{
|
|
||||||
O (error, NILF, _("windows32_openpipe(): process_init_fd() failed\n"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure that CreateProcess() has Path it needs */
|
|
||||||
sync_Path_environment ();
|
|
||||||
/* 'sync_Path_environment' may realloc 'environ', so take note of
|
|
||||||
the new value. */
|
|
||||||
envp = environ;
|
|
||||||
|
|
||||||
if (! process_begin (hProcess, command_argv, envp, command_argv[0], NULL))
|
|
||||||
{
|
|
||||||
/* register process for wait */
|
|
||||||
process_register (hProcess);
|
|
||||||
|
|
||||||
/* set the pid for returning to caller */
|
|
||||||
*pid_p = (pid_t) hProcess;
|
|
||||||
|
|
||||||
/* set up to read data from child */
|
|
||||||
pipedes[0] = _open_osfhandle ((intptr_t) hChildOutRd, O_RDONLY);
|
|
||||||
|
|
||||||
/* this will be closed almost right away */
|
|
||||||
pipedes[1] = _open_osfhandle ((intptr_t) hChildOutWr, O_APPEND);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* reap/cleanup the failed process */
|
|
||||||
process_cleanup (hProcess);
|
|
||||||
|
|
||||||
/* close handles which were duplicated, they weren't used */
|
|
||||||
if (hIn != INVALID_HANDLE_VALUE)
|
|
||||||
CloseHandle (hIn);
|
|
||||||
if (hErr != INVALID_HANDLE_VALUE)
|
|
||||||
CloseHandle (hErr);
|
|
||||||
|
|
||||||
/* close pipe handles, they won't be used */
|
|
||||||
CloseHandle (hChildOutRd);
|
|
||||||
CloseHandle (hChildOutWr);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do shell spawning, with the naughty bits for different OSes.
|
Do shell spawning, with the naughty bits for different OSes.
|
||||||
|
@ -1607,26 +1460,13 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||||
int pipedes[2];
|
int pipedes[2];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
#ifndef __MSDOS__
|
|
||||||
#ifdef WINDOWS32
|
|
||||||
/* Reset just_print_flag. This is needed on Windows when batch files
|
|
||||||
are used to run the commands, because we normally refrain from
|
|
||||||
creating batch files under -n. */
|
|
||||||
int j_p_f = just_print_flag;
|
|
||||||
just_print_flag = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Construct the argument list. */
|
/* Construct the argument list. */
|
||||||
command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
|
command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
|
||||||
&batch_filename);
|
&batch_filename);
|
||||||
if (command_argv == 0)
|
if (command_argv == 0)
|
||||||
{
|
{
|
||||||
#ifdef WINDOWS32
|
|
||||||
just_print_flag = j_p_f;
|
|
||||||
#endif
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
#endif /* !__MSDOS__ */
|
|
||||||
|
|
||||||
/* Using a target environment for 'shell' loses in cases like:
|
/* Using a target environment for 'shell' loses in cases like:
|
||||||
export var = $(shell echo foobie)
|
export var = $(shell echo foobie)
|
||||||
|
@ -1648,21 +1488,6 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||||
errfd = (output_context && output_context->err >= 0
|
errfd = (output_context && output_context->err >= 0
|
||||||
? output_context->err : FD_STDERR);
|
? output_context->err : FD_STDERR);
|
||||||
|
|
||||||
#if defined(WINDOWS32)
|
|
||||||
windows32_openpipe (pipedes, errfd, &pid, command_argv, envp);
|
|
||||||
/* Restore the value of just_print_flag. */
|
|
||||||
just_print_flag = j_p_f;
|
|
||||||
|
|
||||||
if (pipedes[0] < 0)
|
|
||||||
{
|
|
||||||
/* Open of the pipe failed, mark as failed execution. */
|
|
||||||
shell_completed (127, 0);
|
|
||||||
OS (error, reading_file, "pipe: %s", strerror (errno));
|
|
||||||
pid = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
if (pipe (pipedes) < 0)
|
if (pipe (pipedes) < 0)
|
||||||
{
|
{
|
||||||
OS (error, reading_file, "pipe: %s", strerror (errno));
|
OS (error, reading_file, "pipe: %s", strerror (errno));
|
||||||
|
@ -1692,7 +1517,6 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||||
shell_completed (127, 0);
|
shell_completed (127, 0);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
{
|
{
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
@ -1798,7 +1622,6 @@ func_eq (char *o, char **argv, char *funcname UNUSED)
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
string-boolean not operator.
|
string-boolean not operator.
|
||||||
*/
|
*/
|
||||||
|
@ -1815,17 +1638,8 @@ func_not (char *o, char **argv, char *funcname UNUSED)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DOS_PATHS
|
#define IS_ABSOLUTE(n) (n[0] == '/')
|
||||||
# ifdef __CYGWIN__
|
#define ROOT_LEN 1
|
||||||
# define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || STOP_SET (n[0], MAP_DIRSEP))
|
|
||||||
# else
|
|
||||||
# define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
|
|
||||||
# endif
|
|
||||||
# define ROOT_LEN 3
|
|
||||||
#else
|
|
||||||
# define IS_ABSOLUTE(n) (n[0] == '/')
|
|
||||||
# define ROOT_LEN 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return the absolute name of file NAME which does not contain any '.',
|
/* Return the absolute name of file NAME which does not contain any '.',
|
||||||
'..' components nor any repeated path separators ('/'). */
|
'..' components nor any repeated path separators ('/'). */
|
||||||
|
@ -1849,52 +1663,15 @@ abspath (const char *name, char *apath)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
strcpy (apath, starting_directory);
|
strcpy (apath, starting_directory);
|
||||||
|
|
||||||
#ifdef HAVE_DOS_PATHS
|
|
||||||
if (STOP_SET (name[0], MAP_DIRSEP))
|
|
||||||
{
|
|
||||||
if (STOP_SET (name[1], MAP_DIRSEP))
|
|
||||||
{
|
|
||||||
/* A UNC. Don't prepend a drive letter. */
|
|
||||||
apath[0] = name[0];
|
|
||||||
apath[1] = name[1];
|
|
||||||
root_len = 2;
|
|
||||||
}
|
|
||||||
/* We have /foo, an absolute file name except for the drive
|
|
||||||
letter. Assume the missing drive letter is the current
|
|
||||||
drive, which we can get if we remove from starting_directory
|
|
||||||
everything past the root directory. */
|
|
||||||
apath[root_len] = '\0';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dest = strchr (apath, '\0');
|
dest = strchr (apath, '\0');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(__CYGWIN__) && defined(HAVE_DOS_PATHS)
|
|
||||||
if (STOP_SET (name[0], MAP_DIRSEP))
|
|
||||||
root_len = 1;
|
|
||||||
#endif
|
|
||||||
memcpy (apath, name, root_len);
|
memcpy (apath, name, root_len);
|
||||||
apath[root_len] = '\0';
|
apath[root_len] = '\0';
|
||||||
dest = apath + root_len;
|
dest = apath + root_len;
|
||||||
/* Get past the root, since we already copied it. */
|
/* Get past the root, since we already copied it. */
|
||||||
name += root_len;
|
name += root_len;
|
||||||
#ifdef HAVE_DOS_PATHS
|
|
||||||
if (! STOP_SET (apath[root_len - 1], MAP_DIRSEP))
|
|
||||||
{
|
|
||||||
/* Convert d:foo into d:./foo and increase root_len. */
|
|
||||||
apath[2] = '.';
|
|
||||||
apath[3] = '/';
|
|
||||||
dest++;
|
|
||||||
root_len++;
|
|
||||||
/* strncpy above copied one character too many. */
|
|
||||||
name--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
apath[root_len - 1] = '/'; /* make sure it's a forward slash */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (start = end = name; *start != '\0'; start = end)
|
for (start = end = name; *start != '\0'; start = end)
|
||||||
|
|
Loading…
Reference in a new issue