mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 21:09:22 +08:00
* Makefile.in: Add cygheap.o.
* child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
This commit is contained in:
parent
39630fe3a1
commit
b0e82b74fb
@ -1,3 +1,70 @@
|
||||
Sun Sep 3 00:07:32 2000 Christopher Faylor <cgf@cygnus.com>
|
||||
|
||||
* Makefile.in: Add cygheap.o.
|
||||
* child_info.h: Add specific exec class.
|
||||
* cygheap.h: New file. Contains declarations for cygwin heap.
|
||||
* cygheap.cc: New file. Implements cygwin heap functions.
|
||||
* dcrt0.cc (quoted): Simplify due to new method for passing arguments
|
||||
between cygwin programs.
|
||||
(alloc_stack_hard_way): Attempt to handle overlapped stack.
|
||||
(dll_crt0_1): Move child_info processing here. Accomodate new method
|
||||
for passing arguments between cygwin programs. Initialize cygwin heap.
|
||||
Establish __argc and __argv variables.
|
||||
(_dll_crt0): Move most of child_info processing to dll_crt0_1.
|
||||
(cygwin_dll_init): Remove duplication.
|
||||
* dtable.cc (dtable::extend): Allocate dtable using cygwin heap.
|
||||
(dtable::build_fhandler): Ditto for fhandler type being constructed.
|
||||
(dtable::dup_worker): Free new fhandler from cygwin heap on error.
|
||||
(dtable::select_*): Don't assume that this == fdtab.
|
||||
(dtable::linearize_fd_array): Delete.
|
||||
(dtable::delinearize_fd_array): Delete.
|
||||
(dtable::fixup_after_exec): New file.
|
||||
(dtable::vfork_child_dup): Use cygwin heap.
|
||||
(dtable::vfork_parent_restore): Ditto.
|
||||
* dtable.h: Remove obsolete methods. Add new method.
|
||||
* environ.cc (posify): Eliminate already_posix parameter and logic.
|
||||
(envsize): New function.
|
||||
(_addenv): Use envsize.
|
||||
(environ_init): Accept an argument pointing to an existing environment
|
||||
list. If supplied, allocate space for this in the the program's heap.
|
||||
* fhandler.cc (fhandler_base::operator =): Move here from fhandler.h.
|
||||
Use cygwin heap to allocate filenames.
|
||||
(fhandler_base::set_name): Allocate/free names from cygwin heap.
|
||||
(fhandler_base::linearize): Delete.
|
||||
(fhandler_base::de_linearize): Delete.
|
||||
(fhandler_base::operator delete): Free from cygwin heap.
|
||||
(fhandler_base::~fhandler_base): Ditto.
|
||||
* fhandler.h: Accomodate elimination of *linearize and other changes
|
||||
above.
|
||||
* fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from
|
||||
de_linearize.
|
||||
* heap.h: New file.
|
||||
* fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin
|
||||
heap for name. fhandler_tty::fixup_after_exec): Rename from
|
||||
de_linearize.
|
||||
* fork.cc (fork): Call cygheap_fixup_in_child.
|
||||
* heap.cc: Use declarations in heap.h.
|
||||
* malloc.cc: Sprinkle assertions throughout to catch attempts to
|
||||
free/realloc something from the cygwin heap.
|
||||
* path.cc: Throughout, eliminate use of per-thread cache for cwd. Use
|
||||
cwd_* functions rather than cwd_* variables to access cwd_win32 and
|
||||
cwd_posix.
|
||||
(cwd_win32): New function.
|
||||
(cwd_posix): New function.
|
||||
(cwd_hash): New function.
|
||||
(cwd_fixup_after_exec): New function.
|
||||
* path.h: Accomodate path.cc changes.
|
||||
* pinfo.cc (pinfo_init): Accept a pointer to an environment table.
|
||||
Pass this to environ_init. Eliminate old 'title' tests.
|
||||
* pinfo.h: Accomodate above change in argument.
|
||||
* spawn.cc (struct av): New method for building argv list.
|
||||
(av::unshift): New method.
|
||||
(spawn_guts): Allocate everything that the child process needs in the
|
||||
cygwin heap and pass a pointer to this to the child. Build argv list
|
||||
using new method. Eliminate delinearize stuff.
|
||||
* thread.h: Eliminate _cwd_win32 and _cwd_posix buffers.
|
||||
* winsup.h: Eliminate obsolete functions. Add envsize() declaration.
|
||||
|
||||
2000-09-02 Egor Duda <deo@logos-m.ru>
|
||||
|
||||
* Makefile.in: Remove "make check" support. It is now in
|
||||
|
@ -50,7 +50,7 @@ DEFS = @DEFS@
|
||||
CC:=@CC@
|
||||
# FIXME: Which is it, CC or CC_FOR_TARGET?
|
||||
CC_FOR_TARGET:=$(CC)
|
||||
CFLAGS:=@CFLAGS@ -MD
|
||||
CFLAGS:=@CFLAGS@ -MD -fno-implement-inlines
|
||||
CXXFLAGS:=@CXXFLAGS@
|
||||
|
||||
# For linking mount, etc. crt0.o isn't accessable in a fresh build.
|
||||
@ -116,16 +116,17 @@ EXTRA_OFILES=$(bupdir1)/libiberty/random.o $(bupdir1)/libiberty/strsignal.o
|
||||
|
||||
DLL_IMPORTS:=$(w32api_lib)/libkernel32.a
|
||||
|
||||
DLL_OFILES:=assert.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o dll_init.o \
|
||||
dtable.o environ.o errno.o exceptions.o exec.o external.o fcntl.o \
|
||||
fhandler.o fhandler_console.o fhandler_floppy.o fhandler_random.o \
|
||||
fhandler_raw.o fhandler_serial.o fhandler_tape.o fhandler_termios.o \
|
||||
fhandler_tty.o fhandler_windows.o fhandler_zero.o fork.o glob.o grp.o \
|
||||
heap.o init.o ioctl.o localtime.o malloc.o mmap.o net.o ntea.o passwd.o \
|
||||
path.o pinfo.o pipe.o poll.o regexp.o regerror.o regsub.o registry.o \
|
||||
resource.o scandir.o security.o select.o shared.o signal.o sigproc.o \
|
||||
smallprint.o spawn.o strace.o strsep.o sync.o syscalls.o sysconf.o \
|
||||
syslog.o termios.o times.o tty.o uinfo.o uname.o wait.o window.o \
|
||||
DLL_OFILES:=assert.o cygheap.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o \
|
||||
dll_init.o dtable.o environ.o errno.o exceptions.o exec.o external.o \
|
||||
fcntl.o fhandler.o fhandler_console.o fhandler_floppy.o \
|
||||
fhandler_random.o fhandler_raw.o fhandler_serial.o fhandler_tape.o \
|
||||
fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \
|
||||
fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o mmap.o \
|
||||
net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o regexp.o regerror.o \
|
||||
regsub.o registry.o resource.o scandir.o security.o select.o shared.o \
|
||||
signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o sync.o \
|
||||
syscalls.o sysconf.o syslog.o termios.o times.o tty.o uinfo.o uname.o \
|
||||
wait.o window.o \
|
||||
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MT_SAFE_OBJECTS)
|
||||
|
||||
GMON_OFILES:= gmon.o mcount.o profil.o
|
||||
|
@ -45,7 +45,7 @@ __assert (const char *file, int line, const char *failedexpr)
|
||||
failedexpr, file, line);
|
||||
}
|
||||
|
||||
abort ();
|
||||
abort (); // FIXME: Someday this should work.
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
@ -14,8 +14,9 @@ enum
|
||||
PROC_FORK = PROC_MAGIC + 1,
|
||||
PROC_EXEC = PROC_MAGIC + 2,
|
||||
PROC_SPAWN = PROC_MAGIC + 3,
|
||||
PROC_FORK1 = PROC_MAGIC + 4 // Newer versions provide stack
|
||||
PROC_FORK1 = PROC_MAGIC + 4, // Newer versions provide stack
|
||||
// location information
|
||||
PROC_SPAWN1 = PROC_MAGIC + 5
|
||||
};
|
||||
|
||||
#define PROC_MAGIC_MASK 0xff00f000
|
||||
@ -34,12 +35,6 @@ public:
|
||||
HANDLE shared_h;
|
||||
HANDLE console_h;
|
||||
HANDLE parent_alive; // handle of thread used to track children
|
||||
HANDLE myself_pinfo;
|
||||
~child_info ()
|
||||
{
|
||||
if (myself_pinfo)
|
||||
CloseHandle (myself_pinfo);
|
||||
}
|
||||
};
|
||||
|
||||
class child_info_fork: public child_info
|
||||
@ -55,9 +50,53 @@ public:
|
||||
void *stackbottom; // location of bottom of parent stack
|
||||
};
|
||||
|
||||
class fhandler_base;
|
||||
|
||||
class cygheap_exec_info
|
||||
{
|
||||
public:
|
||||
char *old_title;
|
||||
fhandler_base **fds;
|
||||
size_t nfds;
|
||||
int argc;
|
||||
char **argv;
|
||||
char **environ;
|
||||
HANDLE myself_pinfo;
|
||||
char *cwd_posix;
|
||||
char *cwd_win32;
|
||||
DWORD cwd_hash;
|
||||
};
|
||||
|
||||
class child_info_spawn: public child_info
|
||||
{
|
||||
public:
|
||||
HANDLE parent;
|
||||
void *cygheap;
|
||||
void *cygheap_max;
|
||||
cygheap_exec_info *moreinfo;
|
||||
|
||||
child_info_spawn (): parent (NULL), cygheap (NULL),
|
||||
cygheap_max (NULL), moreinfo (NULL) {}
|
||||
~child_info_spawn ()
|
||||
{
|
||||
if (parent)
|
||||
CloseHandle (parent);
|
||||
if (moreinfo)
|
||||
{
|
||||
if (moreinfo->old_title)
|
||||
cfree (moreinfo->old_title);
|
||||
if (moreinfo->environ)
|
||||
{
|
||||
for (char **e = moreinfo->environ; *e; e++)
|
||||
cfree (*e);
|
||||
cfree (moreinfo->environ);
|
||||
}
|
||||
CloseHandle (moreinfo->myself_pinfo);
|
||||
cfree (moreinfo);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void __stdcall init_child_info (DWORD, child_info *, int, HANDLE);
|
||||
|
||||
extern child_info_fork *child_proc_info;
|
||||
|
||||
/* non-NULL if this process is a child of a cygwin process */
|
||||
extern HANDLE parent_alive;
|
||||
|
232
winsup/cygwin/cygheap.cc
Normal file
232
winsup/cygwin/cygheap.cc
Normal file
@ -0,0 +1,232 @@
|
||||
/* cygheap.cc: Cygwin heap manager.
|
||||
|
||||
Copyright 2000 Cygnus Solutions.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include <errno.h>
|
||||
#include <fhandler.h>
|
||||
#include <assert.h>
|
||||
#include "cygheap.h"
|
||||
#include "heap.h"
|
||||
#include "cygerrno.h"
|
||||
|
||||
#define HEAP_START ((void *) 0x12010000)
|
||||
inline static void
|
||||
init_cheap ()
|
||||
{
|
||||
if (!VirtualAlloc (HEAP_START, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS))
|
||||
api_fatal ("Couldn't reserve space for child's heap, %E");
|
||||
cygheap = cygheap_max = HEAP_START;
|
||||
}
|
||||
|
||||
#define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1)))
|
||||
static void *__stdcall
|
||||
_csbrk (int sbs)
|
||||
{
|
||||
void *lastheap;
|
||||
if (!cygheap)
|
||||
init_cheap ();
|
||||
lastheap = cygheap_max;
|
||||
(char *) cygheap_max += sbs;
|
||||
void *heapalign = (void *) pagetrunc (lastheap);
|
||||
int needalloc = sbs && ((heapalign == lastheap) || heapalign != pagetrunc (cygheap_max));
|
||||
if (needalloc && !VirtualAlloc (lastheap, (DWORD) sbs, MEM_COMMIT, PAGE_READWRITE))
|
||||
api_fatal ("couldn't commit memory for cygwin heap, %E");
|
||||
|
||||
return lastheap;
|
||||
}
|
||||
|
||||
/* Copyright (C) 1997, 2000 DJ Delorie */
|
||||
|
||||
char *buckets[32] = {0};
|
||||
int bucket2size[32] = {0};
|
||||
|
||||
static inline int
|
||||
size2bucket (int size)
|
||||
{
|
||||
int rv = 0x1f;
|
||||
int bit = ~0x10;
|
||||
int i;
|
||||
|
||||
if (size < 4)
|
||||
size = 4;
|
||||
size = (size + 3) & ~3;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (bucket2size[rv & bit] >= size)
|
||||
rv &= bit;
|
||||
bit >>= 1;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_buckets ()
|
||||
{
|
||||
unsigned b;
|
||||
for (b = 0; b < 32; b++)
|
||||
bucket2size[b] = (1 << b);
|
||||
}
|
||||
|
||||
static void *__stdcall
|
||||
_cmalloc (int size)
|
||||
{
|
||||
char *rv;
|
||||
int b;
|
||||
|
||||
if (bucket2size[0] == 0)
|
||||
init_buckets ();
|
||||
|
||||
b = size2bucket (size);
|
||||
if (buckets[b])
|
||||
{
|
||||
rv = buckets[b];
|
||||
buckets[b] = *(char **) rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
size = bucket2size[b] + 4;
|
||||
rv = (char *) _csbrk (size);
|
||||
|
||||
*(int *) rv = b;
|
||||
rv += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void __stdcall
|
||||
_cfree (void *ptr)
|
||||
{
|
||||
int b = *(int *) ((char *) ptr - 4);
|
||||
*(char **) ptr = buckets[b];
|
||||
buckets[b] = (char *) ptr;
|
||||
}
|
||||
|
||||
static void *__stdcall
|
||||
_crealloc (void *ptr, int size)
|
||||
{
|
||||
char *newptr;
|
||||
int oldsize = bucket2size[*(int *) ((char *) ptr - 4)];
|
||||
if (size <= oldsize)
|
||||
return ptr;
|
||||
newptr = (char *) _cmalloc (size);
|
||||
memcpy (newptr, ptr, oldsize);
|
||||
_cfree (ptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
/* End Copyright (C) 1997 DJ Delorie */
|
||||
|
||||
void *cygheap = NULL;
|
||||
void *cygheap_max = NULL;
|
||||
|
||||
#define sizeof_cygheap(n) ((n) + sizeof(cygheap_entry))
|
||||
|
||||
struct cygheap_entry
|
||||
{
|
||||
cygheap_types type;
|
||||
char data[0];
|
||||
};
|
||||
|
||||
#define N ((cygheap_entry *) NULL)
|
||||
#define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data)))
|
||||
|
||||
void
|
||||
cygheap_init ()
|
||||
{
|
||||
if (!cygheap)
|
||||
init_cheap ();
|
||||
}
|
||||
|
||||
extern "C" void __stdcall
|
||||
cygheap_fixup_in_child (HANDLE parent)
|
||||
{
|
||||
DWORD m, n;
|
||||
n = (DWORD) cygheap_max - (DWORD) cygheap;
|
||||
if (!VirtualAlloc (cygheap, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS))
|
||||
api_fatal ("Couldn't reserve space for child's heap, %E");
|
||||
|
||||
if (!VirtualAlloc (cygheap, n, MEM_COMMIT, PAGE_READWRITE))
|
||||
api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
|
||||
cygheap, n);
|
||||
m = 0;
|
||||
n = (DWORD) pagetrunc (n + 4095);
|
||||
if (!ReadProcessMemory (parent, cygheap, cygheap, n, &m) ||
|
||||
m != n)
|
||||
api_fatal ("Couldn't read parent's cygwin heap %d bytes != %d, %E",
|
||||
n, m);
|
||||
}
|
||||
|
||||
static void *__stdcall
|
||||
creturn (cygheap_types x, cygheap_entry * c, int len)
|
||||
{
|
||||
if (!c)
|
||||
{
|
||||
__seterrno ();
|
||||
return NULL;
|
||||
}
|
||||
c->type = x;
|
||||
if (cygheap_max < ((char *) c + len))
|
||||
cygheap_max = (char *) c + len;
|
||||
return (void *) c->data;
|
||||
}
|
||||
|
||||
extern "C" void *__stdcall
|
||||
cmalloc (cygheap_types x, DWORD n)
|
||||
{
|
||||
cygheap_entry *c;
|
||||
c = (cygheap_entry *) _cmalloc (sizeof_cygheap (n));
|
||||
if (!c)
|
||||
system_printf ("cmalloc returned NULL");
|
||||
return creturn (x, c, n);
|
||||
}
|
||||
|
||||
extern "C" void *__stdcall
|
||||
crealloc (void *s, DWORD n)
|
||||
{
|
||||
if (s == NULL)
|
||||
return cmalloc (HEAP_STR, n); // kludge
|
||||
|
||||
assert (!inheap (s));
|
||||
cygheap_entry *c = tocygheap (s);
|
||||
cygheap_types t = c->type;
|
||||
c = (cygheap_entry *) _crealloc (c, sizeof_cygheap (n));
|
||||
if (!c)
|
||||
system_printf ("crealloc returned NULL");
|
||||
return creturn (t, c, n);
|
||||
}
|
||||
|
||||
extern "C" void __stdcall
|
||||
cfree (void *s)
|
||||
{
|
||||
assert (!inheap (s));
|
||||
(void) _cfree (tocygheap (s));
|
||||
}
|
||||
|
||||
extern "C" void *__stdcall
|
||||
ccalloc (cygheap_types x, DWORD n, DWORD size)
|
||||
{
|
||||
cygheap_entry *c;
|
||||
c = (cygheap_entry *) _cmalloc (sizeof_cygheap (n * size));
|
||||
if (c)
|
||||
memset (c->data, 0, size);
|
||||
if (!c)
|
||||
system_printf ("ccalloc returned NULL");
|
||||
return creturn (x, c, n);
|
||||
}
|
||||
|
||||
extern "C" char *__stdcall
|
||||
cstrdup (const char *s)
|
||||
{
|
||||
char *p = (char *) cmalloc (HEAP_STR, strlen (s) + 1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
strcpy (p, s);
|
||||
return p;
|
||||
}
|
37
winsup/cygwin/cygheap.h
Normal file
37
winsup/cygwin/cygheap.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* cygheap.h: Cygwin heap manager.
|
||||
|
||||
Copyright 2000 Cygnus Solutions.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#undef cfree
|
||||
|
||||
enum cygheap_types
|
||||
{
|
||||
HEAP_FHANDLER,
|
||||
HEAP_STR,
|
||||
HEAP_ARGV,
|
||||
HEAP_EXEC,
|
||||
HEAP_BUF
|
||||
};
|
||||
|
||||
#define CYGHEAPSIZE ((1000 * sizeof (fhandler_union)) + (2 * 65536))
|
||||
|
||||
extern HANDLE cygheap;
|
||||
extern HANDLE cygheap_max;
|
||||
|
||||
#define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap) + CYGHEAPSIZE))
|
||||
|
||||
void cygheap_init ();
|
||||
extern "C" {
|
||||
void __stdcall cfree (void *);
|
||||
void __stdcall cygheap_fixup_in_child (HANDLE);
|
||||
void *__stdcall cmalloc (cygheap_types, DWORD);
|
||||
void *__stdcall crealloc (void *, DWORD);
|
||||
void *__stdcall ccalloc (cygheap_types, DWORD, DWORD);
|
||||
char *__stdcall cstrdup (const char *);
|
||||
}
|
@ -20,6 +20,8 @@ details. */
|
||||
#include "sigproc.h"
|
||||
#include "perthread.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
#include "heap.h"
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
#include "child_info.h"
|
||||
@ -293,17 +295,28 @@ quoted (char *cmd, int winshell)
|
||||
char *p;
|
||||
char quote = *cmd;
|
||||
|
||||
/* If this is being run from a Windows shell then we have
|
||||
to preserve quotes for globify to play with later. */
|
||||
if (winshell)
|
||||
if (!winshell)
|
||||
{
|
||||
char *p;
|
||||
strcpy (cmd, cmd + 1);
|
||||
if ((p = strchr (cmd, quote)) != NULL)
|
||||
strcpy (p, p + 1);
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
/* This must have been run from a Windows shell, so preserve
|
||||
quotes for globify to play with later. */
|
||||
while (*++cmd)
|
||||
if ((p = strchr (cmd, quote)) == NULL)
|
||||
if ((p = strpbrk (cmd, "\\\"")) == NULL)
|
||||
{
|
||||
cmd = strchr (cmd, '\0'); // no closing quote
|
||||
break;
|
||||
}
|
||||
else if (p[1] == quote && p[-1] != '\\')
|
||||
else if (quote == '\'')
|
||||
continue;
|
||||
else if (*p == '\\')
|
||||
cmd = ++p;
|
||||
else if (p[1] == quote)
|
||||
{
|
||||
*p = '\\';
|
||||
cmd = ++p; // a quoted quote
|
||||
@ -316,37 +329,6 @@ quoted (char *cmd, int winshell)
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* When running as a child of a cygwin process, the quoted
|
||||
characters should have been placed here by spawn_guts, so
|
||||
we'll just pinch them out of the command string unless
|
||||
they're quoted with a preceding \ */
|
||||
p = cmd + 1;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '\\' && p[1] == '\\')
|
||||
{
|
||||
strcpy (p, p + 1);
|
||||
p++;
|
||||
}
|
||||
else if (*p != quote)
|
||||
p++;
|
||||
else if (p[-1] == '\\')
|
||||
strcpy (p - 1, p);
|
||||
else if (p[1] == quote)
|
||||
{
|
||||
strcpy (p, p + 1);
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (p, p + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
strcpy (cmd, cmd + 1);
|
||||
return p - 1;
|
||||
}
|
||||
|
||||
/* Perform a glob on word if it contains wildcard characters.
|
||||
Also quote every character between quotes to force glob to
|
||||
treat the characters literally. */
|
||||
@ -494,7 +476,8 @@ build_argv (char *cmd, char **&argv, int &argc, int winshell)
|
||||
}
|
||||
|
||||
argv[argc] = NULL;
|
||||
debug_printf ("argv[%d] = '%s'\n", argc, argv[argc]);
|
||||
|
||||
debug_printf ("argc %d", argc);
|
||||
}
|
||||
|
||||
/* sanity and sync check */
|
||||
@ -532,22 +515,35 @@ check_sanity_and_sync (per_process *p)
|
||||
}
|
||||
|
||||
static NO_COPY STARTUPINFO si;
|
||||
# define ciresrv ((struct child_info_fork *)(si.lpReserved2))
|
||||
# define fork_info ((struct child_info_fork *)(si.lpReserved2))
|
||||
# define spawn_info ((struct child_info_spawn *)(si.lpReserved2))
|
||||
child_info_fork NO_COPY *child_proc_info = NULL;
|
||||
static MEMORY_BASIC_INFORMATION sm;
|
||||
|
||||
#define EBP 6
|
||||
#define ESP 7
|
||||
|
||||
extern __inline__ void
|
||||
// __inline__ void
|
||||
extern void
|
||||
alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
|
||||
{
|
||||
void *new_stack_pointer;
|
||||
MEMORY_BASIC_INFORMATION m;
|
||||
void *newbase;
|
||||
int newlen;
|
||||
LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
|
||||
bool noguard;
|
||||
|
||||
if (!VirtualAlloc (ci->stacktop,
|
||||
(DWORD) ci->stackbottom - (DWORD) ci->stacktop,
|
||||
MEM_RESERVE, PAGE_NOACCESS))
|
||||
if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
|
||||
{
|
||||
newbase = curbot;
|
||||
newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
|
||||
noguard = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
newbase = ci->stacktop;
|
||||
newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
|
||||
noguard = 0;
|
||||
}
|
||||
if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
|
||||
api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
|
||||
ci->stacktop, ci->stackbottom);
|
||||
|
||||
@ -559,11 +555,14 @@ alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
|
||||
new_stack_pointer, ci->stacksize);
|
||||
if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
|
||||
api_fatal ("fork: couldn't get new stack info, %E");
|
||||
if (!noguard)
|
||||
{
|
||||
m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
|
||||
if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE|PAGE_GUARD))
|
||||
api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
|
||||
m.BaseAddress);
|
||||
}
|
||||
if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
|
||||
api_fatal ("fork: couldn't get new stack info, %E");
|
||||
ci->stacktop = m.BaseAddress;
|
||||
@ -572,7 +571,7 @@ alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
|
||||
|
||||
/* extend the stack prior to fork longjmp */
|
||||
|
||||
extern __inline__ void
|
||||
static void
|
||||
alloc_stack (child_info_fork *ci)
|
||||
{
|
||||
/* FIXME: adding 16384 seems to avoid a stack copy problem during
|
||||
@ -595,12 +594,9 @@ alloc_stack (child_info_fork *ci)
|
||||
return;
|
||||
}
|
||||
|
||||
/* These must be static due to the way we have to deal with forked
|
||||
processes. */
|
||||
static NO_COPY LPBYTE info = NULL;
|
||||
static NO_COPY int mypid = 0;
|
||||
static int argc = 0;
|
||||
static char **argv = NULL;
|
||||
int _declspec(dllexport) __argc = 0;
|
||||
char _declspec(dllexport) **__argv = NULL;
|
||||
|
||||
void
|
||||
sigthread::init (const char *s)
|
||||
@ -616,22 +612,20 @@ sigthread::init (const char *s)
|
||||
static void
|
||||
dll_crt0_1 ()
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
if (child_proc_info)
|
||||
switch (child_proc_info->type)
|
||||
{
|
||||
case PROC_FORK:
|
||||
case PROC_FORK1:
|
||||
ProtectHandle (child_proc_info->forker_finished);
|
||||
case PROC_EXEC:
|
||||
ProtectHandle (child_proc_info->subproc_ready);
|
||||
}
|
||||
ProtectHandle (hMainProc);
|
||||
ProtectHandle (hMainThread);
|
||||
#endif
|
||||
/* According to onno@stack.urc.tue.nl, the exception handler record must
|
||||
be on the stack. */
|
||||
/* FIXME: Verify forked children get their exception handler set up ok. */
|
||||
exception_list cygwin_except_entry;
|
||||
|
||||
regthread ("main", GetCurrentThreadId ());
|
||||
/* Initialize SIGSEGV handling, etc... Because the exception handler
|
||||
references data in the shared area, this must be done after
|
||||
shared_init. */
|
||||
init_exceptions (&cygwin_except_entry);
|
||||
|
||||
do_global_ctors (&__CTOR_LIST__, 1);
|
||||
|
||||
/* Set the os_being_run global. */
|
||||
set_os_type ();
|
||||
check_sanity_and_sync (user_data);
|
||||
|
||||
/* Nasty static stuff needed by newlib -- point to a local copy of
|
||||
@ -642,10 +636,58 @@ dll_crt0_1 ()
|
||||
|
||||
_impure_ptr = &reent_data;
|
||||
|
||||
#ifdef _MT_SAFE
|
||||
user_data->resourcelocks->Init ();
|
||||
user_data->threadinterface->Init0 ();
|
||||
#endif
|
||||
regthread ("main", GetCurrentThreadId ());
|
||||
|
||||
char **envp = NULL;
|
||||
|
||||
if (child_proc_info)
|
||||
{
|
||||
switch (child_proc_info->type)
|
||||
{
|
||||
case PROC_FORK:
|
||||
case PROC_FORK1:
|
||||
alloc_stack (fork_info);
|
||||
set_myself (mypid);
|
||||
user_data->forkee = child_proc_info->cygpid;
|
||||
user_data->heaptop = child_proc_info->heaptop;
|
||||
user_data->heapbase = child_proc_info->heapbase;
|
||||
user_data->heapptr = child_proc_info->heapptr;
|
||||
ProtectHandle (child_proc_info->forker_finished);
|
||||
break;
|
||||
case PROC_EXEC:
|
||||
case PROC_SPAWN:
|
||||
HANDLE h;
|
||||
cygheap = spawn_info->cygheap;
|
||||
cygheap_max = spawn_info->cygheap_max;
|
||||
cygheap_fixup_in_child (spawn_info->parent);
|
||||
if (!spawn_info->moreinfo->myself_pinfo ||
|
||||
!DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
|
||||
hMainProc, &h, 0, 0,
|
||||
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
||||
h = NULL;
|
||||
set_myself (mypid, h);
|
||||
__argc = spawn_info->moreinfo->argc;
|
||||
__argv = spawn_info->moreinfo->argv;
|
||||
envp = spawn_info->moreinfo->environ;
|
||||
cwd_fixup_after_exec (spawn_info->moreinfo->cwd_win32,
|
||||
spawn_info->moreinfo->cwd_posix,
|
||||
spawn_info->moreinfo->cwd_hash);
|
||||
fdtab.fixup_after_exec (spawn_info->parent, spawn_info->moreinfo->nfds,
|
||||
spawn_info->moreinfo->fds);
|
||||
CloseHandle (spawn_info->parent);
|
||||
if (spawn_info->moreinfo->old_title)
|
||||
{
|
||||
old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
|
||||
cfree (spawn_info->moreinfo->old_title);
|
||||
}
|
||||
ProtectHandle (child_proc_info->subproc_ready);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProtectHandle (hMainProc);
|
||||
ProtectHandle (hMainThread);
|
||||
|
||||
/* Initialize the host dependent constants object. */
|
||||
host_dependent.init ();
|
||||
@ -657,9 +699,6 @@ dll_crt0_1 ()
|
||||
mainthread.init ("mainthread"); // For use in determining if signals
|
||||
// should be blocked.
|
||||
|
||||
if (mypid)
|
||||
set_myself ((pid_t) mypid, NULL);
|
||||
|
||||
(void) SetErrorMode (SEM_FAILCRITICALERRORS);
|
||||
|
||||
/* Initialize the heap. */
|
||||
@ -684,18 +723,20 @@ dll_crt0_1 ()
|
||||
|
||||
NOTE: Don't do anything that involves the stack until you've completed
|
||||
this step. */
|
||||
if (ciresrv->stacksize)
|
||||
if (fork_info->stacksize)
|
||||
{
|
||||
asm ("movl %0,%%fs:4" : : "r" (ciresrv->stackbottom));
|
||||
asm ("movl %0,%%fs:8" : : "r" (ciresrv->stacktop));
|
||||
asm ("movl %0,%%fs:4" : : "r" (fork_info->stackbottom));
|
||||
asm ("movl %0,%%fs:8" : : "r" (fork_info->stacktop));
|
||||
}
|
||||
|
||||
longjmp (ciresrv->jmp, ciresrv->cygpid);
|
||||
longjmp (fork_info->jmp, fork_info->cygpid);
|
||||
}
|
||||
|
||||
/* Initialize our process table entry. Don't use the parent info for
|
||||
dynamically loaded case. */
|
||||
pinfo_init ((dynamically_loaded) ? NULL : info);
|
||||
cygheap_init (); /* Initialize cygwin's heap */
|
||||
cwd_init ();
|
||||
|
||||
/* Initialize our process table entry. */
|
||||
pinfo_init (envp);
|
||||
|
||||
if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
|
||||
old_title = title_buf;
|
||||
@ -740,26 +781,32 @@ dll_crt0_1 ()
|
||||
/* Set up standard fds in file descriptor table. */
|
||||
stdio_init ();
|
||||
|
||||
if (user_data->premain[0])
|
||||
for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
|
||||
user_data->premain[i] (argc, argv);
|
||||
|
||||
if (!__argc)
|
||||
{
|
||||
/* Scan the command line and build argv. Expand wildcards if not
|
||||
called from another cygwin process. */
|
||||
build_argv (line, argv, argc,
|
||||
build_argv (line, __argv, __argc,
|
||||
NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
|
||||
|
||||
/* Convert argv[0] to posix rules if it's currently blatantly
|
||||
win32 style. */
|
||||
if ((strchr (argv[0], ':')) || (strchr (argv[0], '\\')))
|
||||
if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
|
||||
{
|
||||
char *new_argv0 = (char *) alloca (MAX_PATH);
|
||||
cygwin_conv_to_posix_path (argv[0], new_argv0);
|
||||
argv[0] = new_argv0;
|
||||
cygwin_conv_to_posix_path (__argv[0], new_argv0);
|
||||
char *p = strchr (new_argv0, '\0') - 4;
|
||||
if (p > new_argv0 && strcasematch (p, ".exe"))
|
||||
*p = '\0';
|
||||
__argv[0] = new_argv0;
|
||||
}
|
||||
}
|
||||
|
||||
if (user_data->premain[0])
|
||||
for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
|
||||
user_data->premain[i] (__argc, __argv);
|
||||
|
||||
/* Set up __progname for getopt error call. */
|
||||
__progname = argv[0];
|
||||
__progname = __argv[0];
|
||||
|
||||
cygwin_finished_initializing = 1;
|
||||
/* Call init of loaded dlls. */
|
||||
@ -768,7 +815,7 @@ dll_crt0_1 ()
|
||||
/* Execute any specified "premain" functions */
|
||||
if (user_data->premain[PREMAIN_LEN / 2])
|
||||
for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
|
||||
user_data->premain[i] (argc, argv);
|
||||
user_data->premain[i] (__argc, __argv);
|
||||
|
||||
debug_printf ("user_data->main %p", user_data->main);
|
||||
|
||||
@ -785,8 +832,9 @@ dll_crt0_1 ()
|
||||
|
||||
set_errno (0);
|
||||
|
||||
MALLOC_CHECK;
|
||||
if (user_data->main)
|
||||
exit (user_data->main (argc, argv, *user_data->envptr));
|
||||
exit (user_data->main (__argc, __argv, *user_data->envptr));
|
||||
}
|
||||
|
||||
/* Wrap the real one, otherwise gdb gets confused about
|
||||
@ -798,16 +846,7 @@ dll_crt0_1 ()
|
||||
extern "C" void __stdcall
|
||||
_dll_crt0 ()
|
||||
{
|
||||
char zeros[sizeof (ciresrv->zero)] = {0};
|
||||
/* According to onno@stack.urc.tue.nl, the exception handler record must
|
||||
be on the stack. */
|
||||
/* FIXME: Verify forked children get their exception handler set up ok. */
|
||||
exception_list cygwin_except_entry;
|
||||
/* Initialize SIGSEGV handling, etc... Because the exception handler
|
||||
references data in the shared area, this must be done after
|
||||
shared_init. */
|
||||
init_exceptions (&cygwin_except_entry);
|
||||
do_global_ctors (&__CTOR_LIST__, 1);
|
||||
char zeros[sizeof (fork_info->zero)] = {0};
|
||||
|
||||
/* Set the os_being_run global. */
|
||||
set_os_type ();
|
||||
@ -833,62 +872,35 @@ _dll_crt0 ()
|
||||
DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
|
||||
&hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
|
||||
HANDLE h;
|
||||
GetStartupInfo (&si);
|
||||
if (si.cbReserved2 >= EXEC_MAGIC_SIZE &&
|
||||
memcmp (ciresrv->zero, zeros, sizeof (zeros)) == 0)
|
||||
memcmp (fork_info->zero, zeros, sizeof (zeros)) == 0)
|
||||
{
|
||||
switch (ciresrv->type)
|
||||
switch (fork_info->type)
|
||||
{
|
||||
case PROC_EXEC:
|
||||
case PROC_SPAWN:
|
||||
case PROC_FORK:
|
||||
case PROC_FORK1:
|
||||
{
|
||||
HANDLE me = hMainProc;
|
||||
child_proc_info = ciresrv;
|
||||
child_proc_info = fork_info;
|
||||
mypid = child_proc_info->cygpid;
|
||||
cygwin_shared_h = child_proc_info->shared_h;
|
||||
console_shared_h = child_proc_info->console_h;
|
||||
|
||||
/* We don't want subprocesses to inherit this */
|
||||
if (!dynamically_loaded)
|
||||
{
|
||||
if (!DuplicateHandle (me, child_proc_info->parent_alive,
|
||||
me, &parent_alive, 0, 0,
|
||||
if (dynamically_loaded)
|
||||
parent_alive = NULL;
|
||||
else if (!DuplicateHandle (hMainProc, child_proc_info->parent_alive,
|
||||
hMainProc, &parent_alive, 0, 0,
|
||||
DUPLICATE_SAME_ACCESS
|
||||
| DUPLICATE_CLOSE_SOURCE))
|
||||
system_printf ("parent_alive DuplicateHandle failed, %E");
|
||||
}
|
||||
else if (parent_alive)
|
||||
parent_alive = NULL;
|
||||
|
||||
switch (child_proc_info->type)
|
||||
{
|
||||
case PROC_EXEC:
|
||||
case PROC_SPAWN:
|
||||
info = si.lpReserved2 + ciresrv->cb;
|
||||
if (child_proc_info->myself_pinfo &&
|
||||
DuplicateHandle (hMainProc, child_proc_info->myself_pinfo,
|
||||
hMainProc, &h, 0, 0,
|
||||
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
||||
{
|
||||
set_myself (mypid, h);
|
||||
mypid = 0;
|
||||
}
|
||||
break;
|
||||
case PROC_FORK:
|
||||
case PROC_FORK1:
|
||||
user_data->forkee = child_proc_info->cygpid;
|
||||
user_data->heaptop = child_proc_info->heaptop;
|
||||
user_data->heapbase = child_proc_info->heapbase;
|
||||
user_data->heapptr = child_proc_info->heapptr;
|
||||
alloc_stack (ciresrv); // may never return
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if ((ciresrv->type & PROC_MAGIC_MASK) == PROC_MAGIC_GENERIC)
|
||||
if ((fork_info->type & PROC_MAGIC_MASK) == PROC_MAGIC_GENERIC)
|
||||
api_fatal ("conflicting versions of cygwin1.dll detected. Use only the most recent version.\n");
|
||||
}
|
||||
}
|
||||
@ -913,19 +925,6 @@ cygwin_dll_init ()
|
||||
{
|
||||
static char **envp;
|
||||
static int _fmode;
|
||||
/* According to onno@stack.urc.tue.nl, the exception handler record must
|
||||
be on the stack. */
|
||||
/* FIXME: Verify forked children get their exception handler set up ok. */
|
||||
exception_list cygwin_except_entry;
|
||||
/* Initialize SIGSEGV handling, etc... Because the exception handler
|
||||
references data in the shared area, this must be done after
|
||||
shared_init. */
|
||||
init_exceptions (&cygwin_except_entry);
|
||||
do_global_ctors (&__CTOR_LIST__, 1);
|
||||
|
||||
/* Set the os_being_run global. */
|
||||
set_os_type ();
|
||||
|
||||
user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
|
||||
|
||||
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
|
||||
|
@ -23,6 +23,7 @@ details. */
|
||||
#include "sync.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
#include "path.h"
|
||||
@ -62,7 +63,7 @@ dtable::extend (int howmuch)
|
||||
/* Try to allocate more space for fd table. We can't call realloc()
|
||||
here to preserve old table if memory allocation fails */
|
||||
|
||||
if (!(newfds = (fhandler_base **) calloc (new_size, sizeof newfds[0])))
|
||||
if (!(newfds = (fhandler_base **) ccalloc (HEAP_ARGV, new_size, sizeof newfds[0])))
|
||||
{
|
||||
debug_printf ("calloc failed");
|
||||
return 0;
|
||||
@ -70,7 +71,7 @@ dtable::extend (int howmuch)
|
||||
if (fds)
|
||||
{
|
||||
memcpy (newfds, fds, size * sizeof (fds[0]));
|
||||
free (fds);
|
||||
cfree (fds);
|
||||
}
|
||||
|
||||
size = new_size;
|
||||
@ -151,7 +152,7 @@ dtable::release (int fd)
|
||||
{
|
||||
if (!not_open (fd))
|
||||
{
|
||||
delete (fds[fd]);
|
||||
delete fds[fd]; /* CGF FIXME */
|
||||
fds[fd] = NULL;
|
||||
}
|
||||
}
|
||||
@ -240,7 +241,7 @@ fhandler_base *
|
||||
dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit)
|
||||
{
|
||||
fhandler_base *fh;
|
||||
void *buf = calloc (1, sizeof (fhandler_union) + 100);
|
||||
void *buf = ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_union) + 100);
|
||||
|
||||
dev &= FH_DEVMASK;
|
||||
switch (dev)
|
||||
@ -312,7 +313,7 @@ dtable::dup_worker (fhandler_base *oldfh)
|
||||
newfh->set_io_handle (NULL);
|
||||
if (oldfh->dup (newfh))
|
||||
{
|
||||
free (newfh);
|
||||
cfree (newfh);
|
||||
newfh = NULL;
|
||||
return NULL;
|
||||
}
|
||||
@ -351,18 +352,21 @@ dtable::dup2 (int oldfd, int newfd)
|
||||
}
|
||||
|
||||
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
|
||||
if ((size_t) newfd >= fdtab.size)
|
||||
{
|
||||
int inc_size = NOFILE_INCR * ((newfd + NOFILE_INCR - 1) / NOFILE_INCR) -
|
||||
fdtab.size;
|
||||
fdtab.extend (inc_size);
|
||||
}
|
||||
|
||||
if ((size_t) newfd >= fdtab.size || newfd < 0)
|
||||
{
|
||||
syscall_printf ("new fd out of bounds: %d", newfd);
|
||||
set_errno (EBADF);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((size_t) newfd >= fdtab.size)
|
||||
{
|
||||
int inc_size = NOFILE_INCR * ((newfd + NOFILE_INCR - 1) / NOFILE_INCR) -
|
||||
fdtab.size;
|
||||
fdtab.extend (inc_size);
|
||||
}
|
||||
|
||||
if (!not_open (newfd))
|
||||
_close (newfd);
|
||||
fds[newfd] = newfh;
|
||||
@ -382,12 +386,12 @@ done:
|
||||
select_record *
|
||||
dtable::select_read (int fd, select_record *s)
|
||||
{
|
||||
if (fdtab.not_open (fd))
|
||||
if (not_open (fd))
|
||||
{
|
||||
set_errno (EBADF);
|
||||
return NULL;
|
||||
}
|
||||
fhandler_base *fh = fdtab[fd];
|
||||
fhandler_base *fh = fds[fd];
|
||||
s = fh->select_read (s);
|
||||
s->fd = fd;
|
||||
s->fh = fh;
|
||||
@ -399,12 +403,12 @@ dtable::select_read (int fd, select_record *s)
|
||||
select_record *
|
||||
dtable::select_write (int fd, select_record *s)
|
||||
{
|
||||
if (fdtab.not_open (fd))
|
||||
if (not_open (fd))
|
||||
{
|
||||
set_errno (EBADF);
|
||||
return NULL;
|
||||
}
|
||||
fhandler_base *fh = fdtab[fd];
|
||||
fhandler_base *fh = fds[fd];
|
||||
s = fh->select_write (s);
|
||||
s->fd = fd;
|
||||
s->fh = fh;
|
||||
@ -416,12 +420,12 @@ dtable::select_write (int fd, select_record *s)
|
||||
select_record *
|
||||
dtable::select_except (int fd, select_record *s)
|
||||
{
|
||||
if (fdtab.not_open (fd))
|
||||
if (not_open (fd))
|
||||
{
|
||||
set_errno (EBADF);
|
||||
return NULL;
|
||||
}
|
||||
fhandler_base *fh = fdtab[fd];
|
||||
fhandler_base *fh = fds[fd];
|
||||
s = fh->select_except (s);
|
||||
s->fd = fd;
|
||||
s->fh = fh;
|
||||
@ -430,151 +434,33 @@ dtable::select_except (int fd, select_record *s)
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to take an existant dtable array
|
||||
* and linearize it into a memory buffer.
|
||||
* If memory buffer is NULL, it returns the size
|
||||
* of memory buffer needed to do the linearization.
|
||||
* On error returns -1.
|
||||
*/
|
||||
|
||||
int
|
||||
dtable::linearize_fd_array (unsigned char *in_buf, int buflen)
|
||||
/* Function to walk the fd table after an exec and perform
|
||||
per-fhandler type fixups. */
|
||||
void
|
||||
dtable::fixup_after_exec (HANDLE parent, size_t sz, fhandler_base **f)
|
||||
{
|
||||
/* If buf == NULL, just precalculate length */
|
||||
if (in_buf == NULL)
|
||||
{
|
||||
buflen = sizeof (size_t);
|
||||
for (int i = 0, max_used_fd = -1; i < (int)size; i++)
|
||||
if (!not_open (i) && !fds[i]->get_close_on_exec ())
|
||||
{
|
||||
buflen += i - (max_used_fd + 1);
|
||||
buflen += fds[i]->cb + strlen (fds[i]->get_name ()) + 1
|
||||
+ strlen (fds[i]->get_win32_name ()) + 1;
|
||||
max_used_fd = i;
|
||||
}
|
||||
debug_printf ("needed buflen %d", buflen);
|
||||
return buflen;
|
||||
}
|
||||
|
||||
debug_printf ("in_buf = %x, buflen = %d", in_buf, buflen);
|
||||
|
||||
/*
|
||||
* Now linearize each open fd (write a 0xff byte for a closed fd).
|
||||
* Write the name of the open fd first (null terminated). This
|
||||
* allows the de_linearizeing code to determine what kind of fhandler_xxx
|
||||
* to create.
|
||||
*/
|
||||
|
||||
size_t i;
|
||||
int len, total_size;
|
||||
|
||||
total_size = sizeof (size_t);
|
||||
if (total_size > buflen)
|
||||
{
|
||||
system_printf ("FATAL: linearize_fd_array exceeded buffer size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char *buf = in_buf;
|
||||
buf += sizeof (size_t); /* skip over length which is added later */
|
||||
|
||||
for (i = 0, total_size = sizeof (size_t); total_size < buflen; i++)
|
||||
{
|
||||
if (not_open (i) || fds[i]->get_close_on_exec ())
|
||||
{
|
||||
debug_printf ("linearizing closed fd %d",i);
|
||||
*buf = 0xff; /* place holder */
|
||||
len = 1;
|
||||
}
|
||||
size = sz;
|
||||
fds = f;
|
||||
first_fd_for_open = 0;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (fds[i])
|
||||
if (fds[i]->get_close_on_exec ())
|
||||
release (i);
|
||||
else
|
||||
{
|
||||
len = fds[i]->linearize (buf);
|
||||
debug_printf ("fd %d, len %d, name %s, device %p", i, len, buf,
|
||||
fds[i]->get_device ());
|
||||
fds[i]->clear_readahead ();
|
||||
fds[i]->fixup_after_exec (parent);
|
||||
}
|
||||
|
||||
total_size += len;
|
||||
buf += len;
|
||||
}
|
||||
|
||||
i--;
|
||||
memcpy (in_buf, &i, sizeof (size_t));
|
||||
if (total_size != buflen)
|
||||
system_printf ("out of sync %d != %d", total_size, buflen);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to take a linearized dtable array in a memory buffer and
|
||||
* re-create the original dtable array.
|
||||
*/
|
||||
|
||||
LPBYTE
|
||||
dtable::de_linearize_fd_array (LPBYTE buf)
|
||||
{
|
||||
int len, max_used_fd;
|
||||
size_t inc_size;
|
||||
|
||||
debug_printf ("buf %x", buf);
|
||||
|
||||
/* First get the number of fd's - use this to set the fdtabsize.
|
||||
NB. This is the only place in the code this should be done !!
|
||||
*/
|
||||
|
||||
memcpy ((char *) &max_used_fd, buf, sizeof (int));
|
||||
buf += sizeof (size_t);
|
||||
|
||||
inc_size = NOFILE_INCR * ((max_used_fd + NOFILE_INCR - 1) / NOFILE_INCR) -
|
||||
size;
|
||||
debug_printf ("max_used_fd %d, inc size %d", max_used_fd, inc_size);
|
||||
if (inc_size > 0 && !extend (inc_size))
|
||||
{
|
||||
system_printf ("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= max_used_fd; i++)
|
||||
{
|
||||
/* 0xFF means closed */
|
||||
if (*buf == 0xff)
|
||||
{
|
||||
fds[i] = NULL;
|
||||
buf++;
|
||||
debug_printf ("closed fd %d", i);
|
||||
continue;
|
||||
}
|
||||
/* fd was open - de_linearize it */
|
||||
/* Get the null-terminated name. It is followed by an image of
|
||||
the actual fhandler_* structure. Use the status field from
|
||||
this to build a new fhandler type. */
|
||||
|
||||
DWORD status;
|
||||
LPBYTE obuf = buf;
|
||||
char *win32;
|
||||
win32 = strchr ((char *)obuf, '\0') + 1;
|
||||
buf = (LPBYTE)strchr ((char *)win32, '\0') + 1;
|
||||
memcpy ((char *)&status, buf + FHSTATOFF, sizeof(DWORD));
|
||||
debug_printf ("fd %d, name %s, win32 name %s, status %p",
|
||||
i, obuf, win32, status);
|
||||
len = build_fhandler (i, status, (const char *) NULL)->
|
||||
de_linearize ((char *) buf, (char *) obuf, win32);
|
||||
set_std_handle (i);
|
||||
buf += len;
|
||||
debug_printf ("len %d", buf - obuf);
|
||||
}
|
||||
first_fd_for_open = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
dtable::fixup_after_fork (HANDLE parent)
|
||||
{
|
||||
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
|
||||
fhandler_base *fh;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (!not_open (i))
|
||||
if ((fh = fds[i]) != NULL)
|
||||
{
|
||||
fhandler_base *fh = fds[i];
|
||||
if (fh->get_close_on_exec () || fh->get_need_fork_fixup ())
|
||||
{
|
||||
debug_printf ("fd %d(%s)", i, fh->get_name ());
|
||||
@ -588,7 +474,7 @@ int
|
||||
dtable::vfork_child_dup ()
|
||||
{
|
||||
fhandler_base **newtable;
|
||||
newtable = (fhandler_base **) calloc (size, sizeof(fds[0]));
|
||||
newtable = (fhandler_base **) ccalloc (HEAP_ARGV, size, sizeof(fds[0]));
|
||||
int res = 1;
|
||||
|
||||
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
|
||||
@ -601,6 +487,7 @@ dtable::vfork_child_dup ()
|
||||
set_errno (EBADF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fds_on_hold = fds;
|
||||
fds = newtable;
|
||||
out:
|
||||
@ -617,7 +504,7 @@ dtable::vfork_parent_restore ()
|
||||
fhandler_base **deleteme = fds;
|
||||
fds = fds_on_hold;
|
||||
fds_on_hold = NULL;
|
||||
free (deleteme);
|
||||
cfree (deleteme);
|
||||
|
||||
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
|
||||
return;
|
||||
|
@ -30,8 +30,7 @@ public:
|
||||
void release (int fd);
|
||||
void init_std_file_from_handle (int fd, HANDLE handle, DWORD access, const char *name);
|
||||
int dup2 (int oldfd, int newfd);
|
||||
int linearize_fd_array (unsigned char *buf, int buflen);
|
||||
LPBYTE de_linearize_fd_array (LPBYTE buf);
|
||||
void fixup_after_exec (HANDLE, size_t, fhandler_base **);
|
||||
fhandler_base *operator [](int fd) { return fds[fd]; }
|
||||
select_record *select_read (int fd, select_record *s);
|
||||
select_record *select_write (int fd, select_record *s);
|
||||
|
@ -27,6 +27,8 @@ extern DWORD chunksize;
|
||||
BOOL reset_com = TRUE;
|
||||
static BOOL envcache = TRUE;
|
||||
|
||||
static char **lastenviron = NULL;
|
||||
|
||||
/* List of names which are converted from dos to unix
|
||||
* on the way in and back again on the way out.
|
||||
*
|
||||
@ -102,7 +104,7 @@ getwinenv (const char *env, const char *in_posix)
|
||||
/* Convert windows path specs to POSIX, if appropriate.
|
||||
*/
|
||||
static void __stdcall
|
||||
posify (int already_posix, char **here, const char *value)
|
||||
posify (char **here, const char *value)
|
||||
{
|
||||
char *src = *here;
|
||||
win_env *conv;
|
||||
@ -111,10 +113,6 @@ posify (int already_posix, char **here, const char *value)
|
||||
if (!(conv = getwinenv (src)))
|
||||
return;
|
||||
|
||||
if (already_posix)
|
||||
conv->add_cache (value, NULL);
|
||||
else
|
||||
{
|
||||
/* Turn all the items from c:<foo>;<bar> into their
|
||||
mounted equivalents - if there is one. */
|
||||
|
||||
@ -127,7 +125,6 @@ posify (int already_posix, char **here, const char *value)
|
||||
*here = outenv;
|
||||
free (src);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* my_findenv --
|
||||
@ -175,6 +172,16 @@ getenv (const char *name)
|
||||
return my_findenv (name, &offset);
|
||||
}
|
||||
|
||||
extern int __stdcall
|
||||
envsize (const char * const *in_envp, int debug_print)
|
||||
{
|
||||
const char * const *envp;
|
||||
for (envp = in_envp; *envp; envp++)
|
||||
if (debug_print)
|
||||
debug_printf ("%s", *envp);
|
||||
return (1 + envp - in_envp) * sizeof (const char *);
|
||||
}
|
||||
|
||||
/* Takes similar arguments to setenv except that overwrite is
|
||||
either -1, 0, or 1. 0 or 1 signify that the function should
|
||||
perform similarly to setenv. Otherwise putenv is assumed. */
|
||||
@ -202,17 +209,19 @@ _addenv (const char *name, const char *value, int overwrite)
|
||||
}
|
||||
else
|
||||
{ /* Create new slot. */
|
||||
char **env;
|
||||
int sz = envsize (cur_environ ());
|
||||
int allocsz = sz + sizeof (char *);
|
||||
|
||||
/* Search for the end of the environment. */
|
||||
for (env = cur_environ (); *env; env++)
|
||||
continue;
|
||||
|
||||
offset = env - cur_environ (); /* Number of elements currently in environ. */
|
||||
offset = (sz - 1) / sizeof (char *);
|
||||
|
||||
/* Allocate space for additional element plus terminating NULL. */
|
||||
__cygwin_environ = (char **) realloc (cur_environ (), (sizeof (char *) *
|
||||
(offset + 2)));
|
||||
if (__cygwin_environ == lastenviron)
|
||||
lastenviron = __cygwin_environ = (char **) realloc (cur_environ (),
|
||||
allocsz);
|
||||
else if ((lastenviron = (char **) malloc (allocsz)) != NULL)
|
||||
__cygwin_environ = (char **) memcpy ((char **) lastenviron,
|
||||
__cygwin_environ, sz);
|
||||
|
||||
if (!__cygwin_environ)
|
||||
return -1; /* Oops. No more memory. */
|
||||
|
||||
@ -503,18 +512,15 @@ regopt (const char *name)
|
||||
* environment variable and set appropriate options from it.
|
||||
*/
|
||||
void
|
||||
environ_init (int already_posix)
|
||||
environ_init (char **envp)
|
||||
{
|
||||
char *rawenv = GetEnvironmentStrings ();
|
||||
int envsize, i;
|
||||
char *rawenv;
|
||||
int sz, i;
|
||||
char *p;
|
||||
char *newp, **envp;
|
||||
char *newp;
|
||||
int sawTERM = 0;
|
||||
static char cygterm[] = "TERM=cygwin";
|
||||
|
||||
/* Allocate space for environment + trailing NULL + CYGWIN env. */
|
||||
envp = (char **) malloc ((4 + (envsize = 100)) * sizeof (char *));
|
||||
|
||||
regopt ("default");
|
||||
if (myself->progname[0])
|
||||
regopt (myself->progname);
|
||||
@ -525,6 +531,19 @@ environ_init (int already_posix)
|
||||
allow_ntsec = TRUE;
|
||||
#endif
|
||||
|
||||
if (envp)
|
||||
{
|
||||
sz = envsize (envp, 1);
|
||||
char **newenv = (char **) malloc (sz);
|
||||
envp = (char **) memcpy (newenv, envp, sz);
|
||||
cfree (envp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Allocate space for environment + trailing NULL + CYGWIN env. */
|
||||
lastenviron = envp = (char **) malloc ((4 + (sz = 100)) * sizeof (char *));
|
||||
rawenv = GetEnvironmentStrings ();
|
||||
|
||||
/* Current directory information is recorded as variables of the
|
||||
form "=X:=X:\foo\bar; these must be changed into something legal
|
||||
(we could just ignore them but maybe an application will
|
||||
@ -532,8 +551,8 @@ environ_init (int already_posix)
|
||||
for (i = 0, p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1, i++)
|
||||
{
|
||||
newp = strdup (p);
|
||||
if (i >= envsize)
|
||||
envp = (char **) realloc (envp, (4 + (envsize += 100)) *
|
||||
if (i >= sz)
|
||||
envp = (char **) realloc (envp, (4 + (sz += 100)) *
|
||||
sizeof (char *));
|
||||
envp[i] = newp;
|
||||
if (*newp == '=')
|
||||
@ -548,13 +567,16 @@ environ_init (int already_posix)
|
||||
if (strncmp (newp, "CYGWIN=", sizeof("CYGWIN=") - 1) == 0)
|
||||
parse_options (newp + sizeof("CYGWIN=") - 1);
|
||||
if (*eq)
|
||||
posify (already_posix, envp + i, *++eq ? eq : --eq);
|
||||
posify (envp + i, *++eq ? eq : --eq);
|
||||
debug_printf ("%s", envp[i]);
|
||||
}
|
||||
|
||||
if (!sawTERM)
|
||||
envp[i++] = cygterm;
|
||||
envp[i] = NULL;
|
||||
FreeEnvironmentStrings (rawenv);
|
||||
|
||||
out:
|
||||
__cygwin_environ = envp;
|
||||
update_envptrs ();
|
||||
parse_options (NULL);
|
||||
|
@ -13,6 +13,7 @@ details. */
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "cygheap.h"
|
||||
#include <string.h>
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
@ -26,6 +27,20 @@ struct __cygwin_perfile *perfile_table = NULL;
|
||||
|
||||
DWORD binmode = 0;
|
||||
|
||||
inline fhandler_base&
|
||||
fhandler_base::operator =(fhandler_base &x)
|
||||
{
|
||||
memcpy (this, &x, sizeof *this);
|
||||
unix_path_name_ = x.unix_path_name_ ? cstrdup (x.unix_path_name_) : NULL;
|
||||
win32_path_name_ = x.win32_path_name_ ? cstrdup (x.win32_path_name_) : NULL;
|
||||
rabuf = NULL;
|
||||
ralen = 0;
|
||||
raixget = 0;
|
||||
raixput = 0;
|
||||
rabuflen = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_base::puts_readahead (const char *s, size_t len = (size_t) -1)
|
||||
{
|
||||
@ -137,16 +152,16 @@ fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit
|
||||
if (!no_free_names ())
|
||||
{
|
||||
if (unix_path_name_ != NULL && unix_path_name_ != fhandler_disk_dummy_name)
|
||||
free (unix_path_name_);
|
||||
cfree (unix_path_name_);
|
||||
if (win32_path_name_ != NULL && unix_path_name_ != fhandler_disk_dummy_name)
|
||||
free (win32_path_name_);
|
||||
cfree (win32_path_name_);
|
||||
}
|
||||
|
||||
unix_path_name_ = win32_path_name_ = NULL;
|
||||
if (unix_path == NULL || !*unix_path)
|
||||
return;
|
||||
|
||||
unix_path_name_ = strdup (unix_path);
|
||||
unix_path_name_ = cstrdup (unix_path);
|
||||
if (unix_path_name_ == NULL)
|
||||
{
|
||||
system_printf ("fatal error. strdup failed");
|
||||
@ -154,11 +169,11 @@ fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit
|
||||
}
|
||||
|
||||
if (win32_path)
|
||||
win32_path_name_ = strdup (win32_path);
|
||||
win32_path_name_ = cstrdup (win32_path);
|
||||
else
|
||||
{
|
||||
const char *fmt = get_native_name ();
|
||||
win32_path_name_ = (char *) malloc (strlen(fmt) + 16);
|
||||
win32_path_name_ = (char *) cmalloc (HEAP_STR, strlen(fmt) + 16);
|
||||
__small_sprintf (win32_path_name_, fmt, unit);
|
||||
}
|
||||
|
||||
@ -205,37 +220,6 @@ fhandler_base::raw_read (void *ptr, size_t ulen)
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_base::linearize (unsigned char *buf)
|
||||
{
|
||||
unsigned char *orig_buf = buf;
|
||||
#define cbuf ((char *)buf)
|
||||
strcpy (cbuf, get_name() ?: "");
|
||||
char *p = strcpy (strchr (cbuf, '\0') + 1, get_win32_name ());
|
||||
buf = (unsigned char *)memcpy (strchr (p, '\0') + 1, this, cb);
|
||||
debug_printf ("access_ %p, status %p, io_handle %p, output_handle %p",
|
||||
access_, status, get_io_handle (), get_output_handle ());
|
||||
return (buf + cb) - orig_buf;
|
||||
#undef cbuf
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_base::de_linearize (const char *buf, const char *unix_name,
|
||||
const char *win32_name)
|
||||
{
|
||||
int thiscb = cb;
|
||||
memcpy(this, buf, cb);
|
||||
unix_path_name_ = win32_path_name_ = NULL;
|
||||
set_name (unix_name, win32_name);
|
||||
debug_printf ("access_ %p, status %p, io_handle %p, output_handle %p",
|
||||
access_, status, get_io_handle (), get_output_handle ());
|
||||
if (thiscb != cb)
|
||||
system_printf ("mismatch in linearize/delinearize %d != %d", thiscb, cb);
|
||||
raixput = raixget = ralen = rabuflen = 0;
|
||||
rabuf = NULL;
|
||||
return cb;
|
||||
}
|
||||
|
||||
/* Cover function to WriteFile to provide Posix interface and semantics
|
||||
(as much as possible). */
|
||||
int
|
||||
@ -1124,6 +1108,13 @@ fhandler_base::tcgetpgrp (void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_base::operator delete (void *p)
|
||||
{
|
||||
cfree (p);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Normal I/O constructor */
|
||||
fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit):
|
||||
access_ (0),
|
||||
@ -1157,10 +1148,12 @@ fhandler_base::~fhandler_base (void)
|
||||
if (!no_free_names ())
|
||||
{
|
||||
if (unix_path_name_ != NULL && unix_path_name_ != fhandler_disk_dummy_name)
|
||||
free (unix_path_name_);
|
||||
cfree (unix_path_name_);
|
||||
if (win32_path_name_ != NULL && win32_path_name_ != fhandler_disk_dummy_name)
|
||||
free (win32_path_name_);
|
||||
cfree (win32_path_name_);
|
||||
}
|
||||
if (rabuf)
|
||||
free (rabuf);
|
||||
unix_path_name_ = win32_path_name_ = NULL;
|
||||
}
|
||||
|
||||
|
@ -149,13 +149,7 @@ public:
|
||||
void set_name (const char * unix_path, const char * win32_path = NULL,
|
||||
int unit = 0);
|
||||
|
||||
virtual fhandler_base& operator =(fhandler_base &x)
|
||||
{
|
||||
memcpy (this, &x, sizeof *this);
|
||||
unix_path_name_ = x.unix_path_name_ ? strdup (x.unix_path_name_) : NULL;
|
||||
win32_path_name_ = x.win32_path_name_ ? strdup (x.win32_path_name_) : NULL;
|
||||
return *this;
|
||||
};
|
||||
virtual fhandler_base& operator =(fhandler_base &x);
|
||||
fhandler_base (DWORD dev, const char *name = 0, int unit = 0);
|
||||
virtual ~fhandler_base ();
|
||||
|
||||
@ -243,7 +237,8 @@ public:
|
||||
unsigned long get_namehash () { return namehash_; }
|
||||
|
||||
virtual void hclose (HANDLE h) {CloseHandle (h);}
|
||||
virtual void set_inheritance (HANDLE &h, int not_inheriting, const char *name = NULL);
|
||||
virtual void set_inheritance (HANDLE &h, int not_inheriting,
|
||||
const char *name = NULL);
|
||||
|
||||
/* fixup fd possibly non-inherited handles after fork */
|
||||
void fork_fixup (HANDLE parent, HANDLE &h, const char *name);
|
||||
@ -287,10 +282,7 @@ public:
|
||||
virtual int raw_read (void *ptr, size_t ulen);
|
||||
virtual int raw_write (const void *ptr, size_t ulen);
|
||||
|
||||
/* Function to save state of a fhandler_base into memory. */
|
||||
virtual int linearize (unsigned char *);
|
||||
/* Function to de-linearize into a fd */
|
||||
virtual int de_linearize (const char *, const char *, const char *);
|
||||
virtual void fixup_after_exec (HANDLE) {}
|
||||
|
||||
/* Virtual accessor functions to hide the fact
|
||||
that some fd's have two handles. */
|
||||
@ -307,6 +299,12 @@ public:
|
||||
return windows_device_names[FHDEVN (status)];
|
||||
}
|
||||
virtual int bg_check (int) {return 1;}
|
||||
void clear_readahead ()
|
||||
{
|
||||
raixput = raixget = ralen = rabuflen = 0;
|
||||
rabuf = NULL;
|
||||
}
|
||||
void operator delete (void *);
|
||||
};
|
||||
|
||||
class fhandler_socket: public fhandler_base
|
||||
@ -377,9 +375,6 @@ protected:
|
||||
public:
|
||||
~fhandler_dev_raw (void);
|
||||
|
||||
/* Function to de-linearize into a fd */
|
||||
int de_linearize (const char *, const char *, const char *);
|
||||
|
||||
int open (const char *path, int flags, mode_t mode = 0);
|
||||
int close (void);
|
||||
|
||||
@ -497,7 +492,7 @@ public:
|
||||
void dump ();
|
||||
int is_tty () { return 1; }
|
||||
void fixup_after_fork (HANDLE parent);
|
||||
int de_linearize (const char *, const char *, const char *);
|
||||
void fixup_after_exec (HANDLE);
|
||||
|
||||
/* We maintain a pgrp so that tcsetpgrp and tcgetpgrp work, but we
|
||||
don't use it for permissions checking. fhandler_tty_slave does
|
||||
@ -604,7 +599,7 @@ public:
|
||||
select_record *select_write (select_record *s);
|
||||
select_record *select_except (select_record *s);
|
||||
int ready_for_read (int fd, DWORD howlong, int ignra);
|
||||
int de_linearize (const char *, const char *, const char *);
|
||||
void fixup_after_exec (HANDLE);
|
||||
void set_close_on_exec (int val);
|
||||
void fixup_after_fork (HANDLE parent);
|
||||
void set_input_state ()
|
||||
@ -712,7 +707,7 @@ public:
|
||||
int init (int);
|
||||
int init_console ();
|
||||
void fixup_after_fork (HANDLE parent);
|
||||
int de_linearize (const char *, const char *, const char *);
|
||||
void fixup_after_exec (HANDLE);
|
||||
};
|
||||
|
||||
class fhandler_dev_null: public fhandler_base
|
||||
|
@ -8,10 +8,6 @@ This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
/* FIXMES:
|
||||
Should the constructor call tcinit() explicitly rather than having
|
||||
it sprinkled throughout here? */
|
||||
|
||||
#include "winsup.h"
|
||||
#include <sys/termios.h>
|
||||
#include <stdio.h>
|
||||
@ -21,6 +17,7 @@ details. */
|
||||
#include <unistd.h>
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <wincon.h>
|
||||
#include <ctype.h>
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
@ -1404,11 +1401,9 @@ set_console_title (char *title)
|
||||
debug_printf ("title '%s'", buf);
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_console::de_linearize (const char *buf, const char *unix_name,
|
||||
const char *win32_name)
|
||||
void
|
||||
fhandler_console::fixup_after_exec (HANDLE)
|
||||
{
|
||||
int res = fhandler_base::de_linearize (buf, unix_name, win32_name);
|
||||
HANDLE h = get_handle ();
|
||||
HANDLE oh = get_output_handle ();
|
||||
|
||||
@ -1432,5 +1427,5 @@ fhandler_console::de_linearize (const char *buf, const char *unix_name,
|
||||
|
||||
CloseHandle (h);
|
||||
CloseHandle (oh);
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <cygwin/rdevio.h>
|
||||
#include <sys/mtio.h>
|
||||
#include "cygheap.h"
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
#include "path.h"
|
||||
@ -120,23 +121,11 @@ fhandler_dev_raw::fhandler_dev_raw (DWORD devtype, const char *name, int unit) :
|
||||
|
||||
fhandler_dev_raw::~fhandler_dev_raw (void)
|
||||
{
|
||||
delete[]devbuf;
|
||||
if (devbufsiz >= 1L)
|
||||
cfree (devbuf);
|
||||
clear ();
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_raw::de_linearize (const char *buf, const char *unix_name,
|
||||
const char *win32_name)
|
||||
{
|
||||
int ret = fhandler_base::de_linearize (buf, unix_name, win32_name);
|
||||
if (devbufsiz > 1L)
|
||||
{
|
||||
devbuf = new char[devbufsiz];
|
||||
devbufstart = devbufend = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_dev_raw::open (const char *path, int flags, mode_t)
|
||||
{
|
||||
@ -150,7 +139,7 @@ fhandler_dev_raw::open (const char *path, int flags, mode_t)
|
||||
if (ret)
|
||||
{
|
||||
if (devbufsiz > 1L)
|
||||
devbuf = new char[devbufsiz];
|
||||
devbuf = (char *) cmalloc (HEAP_BUF, devbufsiz);
|
||||
}
|
||||
else
|
||||
devbufsiz = 0;
|
||||
@ -456,7 +445,7 @@ fhandler_dev_raw::dup (fhandler_base *child)
|
||||
fhc->devbufsiz = devbufsiz;
|
||||
if (devbufsiz > 1L)
|
||||
{
|
||||
fhc->devbuf = new char[devbufsiz];
|
||||
fhc->devbuf = (char *) cmalloc (HEAP_BUF, devbufsiz);
|
||||
memcpy (fhc->devbuf, devbuf, devbufend);
|
||||
}
|
||||
fhc->devbufstart = devbufstart;
|
||||
@ -499,12 +488,12 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
|
||||
ret = ERROR_INVALID_PARAMETER;
|
||||
else if (!devbuf || op->rd_parm != devbufsiz)
|
||||
{
|
||||
char *buf = new char[op->rd_parm];
|
||||
char *buf = (char *) cmalloc (HEAP_BUF, op->rd_parm);
|
||||
if (devbuf)
|
||||
{
|
||||
memcpy (buf, devbuf + devbufstart, devbufend - devbufstart);
|
||||
devbufend -= devbufstart;
|
||||
delete[]devbuf;
|
||||
cfree (devbuf);
|
||||
}
|
||||
else
|
||||
devbufend = 0;
|
||||
|
@ -867,14 +867,12 @@ fhandler_serial::fixup_after_fork (HANDLE parent)
|
||||
debug_printf ("io_status.hEvent %p", io_status.hEvent);
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_serial::de_linearize (const char *buf, const char *unix_name,
|
||||
const char *win32_name)
|
||||
void
|
||||
fhandler_serial::fixup_after_exec (HANDLE)
|
||||
{
|
||||
int res = fhandler_base::de_linearize (buf, unix_name, win32_name);
|
||||
overlapped_setup ();
|
||||
debug_printf ("io_status.hEvent %p", io_status.hEvent);
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -22,6 +22,7 @@ details. */
|
||||
#include "sync.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
|
||||
/* Tty master stuff */
|
||||
|
||||
@ -433,7 +434,7 @@ fhandler_tty_slave::fhandler_tty_slave(int num, const char *name) :
|
||||
ttynum = num;
|
||||
/* FIXME: This is wasteful. We should rewrite the set_name path to eliminate the
|
||||
need for double allocates. */
|
||||
unix_path_name_ = (char *) realloc (unix_path_name_, strlen(win32_path_name_) + 1);
|
||||
unix_path_name_ = (char *) crealloc (unix_path_name_, strlen(win32_path_name_) + 1);
|
||||
strcpy (unix_path_name_, win32_path_name_);
|
||||
unix_path_name_[0] = unix_path_name_[4] = '/';
|
||||
debug_printf ("unix '%s', win32 '%s'", unix_path_name_, win32_path_name_);
|
||||
@ -1075,14 +1076,12 @@ fhandler_tty_master::fixup_after_fork (HANDLE child)
|
||||
console->fixup_after_fork (child);
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_tty_master::de_linearize (const char *buf, const char *unix_name,
|
||||
const char *win32_name)
|
||||
void
|
||||
fhandler_tty_master::fixup_after_exec (HANDLE)
|
||||
{
|
||||
int res = fhandler_base::de_linearize (buf, unix_name, win32_name);
|
||||
console->close ();
|
||||
init_console ();
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -22,6 +22,7 @@ details. */
|
||||
#include "sync.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
#include "child_info.h"
|
||||
#include "perthread.h"
|
||||
|
||||
@ -567,6 +568,7 @@ fork ()
|
||||
|
||||
MALLOC_CHECK;
|
||||
|
||||
cygheap_fixup_in_child (hParent);
|
||||
fdtab.fixup_after_fork (hParent);
|
||||
signal_fixup_after_fork ();
|
||||
exec_fixup_after_fork ();
|
||||
|
@ -14,12 +14,8 @@ details. */
|
||||
#include "sync.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
#include "heap.h"
|
||||
|
||||
#define brksize ((char *) user_data->heaptop - (char *) user_data->heapbase)
|
||||
#define brk (user_data->heapptr)
|
||||
#define brkbase (user_data->heapbase)
|
||||
#define brktop (user_data->heaptop)
|
||||
#define brkchunk (cygwin_shared->heap_chunk_size ())
|
||||
#define assert(x)
|
||||
|
||||
static unsigned page_const = 0;
|
||||
|
22
winsup/cygwin/heap.h
Normal file
22
winsup/cygwin/heap.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* heap.h: Cygwin heap manager definitions.
|
||||
|
||||
Copyright 2000 Cygnus Solutions.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
/* Heap management. */
|
||||
void heap_init (void);
|
||||
void malloc_init (void);
|
||||
|
||||
#define inheap(s) (brk && ((char *) (s) >= (char *) brkbase) && ((char *) (s) <= (char *) brktop))
|
||||
|
||||
#define brksize ((char *) user_data->heaptop - (char *) user_data->heapbase)
|
||||
#define brk (user_data->heapptr)
|
||||
#define brkbase (user_data->heapbase)
|
||||
#define brktop (user_data->heaptop)
|
||||
#define brkchunk (cygwin_shared->heap_chunk_size ())
|
||||
|
@ -13,6 +13,9 @@ details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "cygheap.h"
|
||||
#include "heap.h"
|
||||
#include "sync.h"
|
||||
|
||||
/* we provide these stubs to call into a user's
|
||||
@ -60,6 +63,8 @@ extern "C" void
|
||||
_free_r (struct _reent *, void *p)
|
||||
{
|
||||
export_malloc_called = 1;
|
||||
assert (!incygheap (p));
|
||||
assert (inheap (p));
|
||||
free (p);
|
||||
}
|
||||
#undef free
|
||||
@ -68,6 +73,8 @@ extern "C" void *
|
||||
_realloc_r (struct _reent *, void *p, size_t size)
|
||||
{
|
||||
export_malloc_called = 1;
|
||||
assert (!incygheap (p));
|
||||
assert (inheap (p));
|
||||
return realloc (p, size);
|
||||
}
|
||||
#undef realloc
|
||||
@ -122,6 +129,22 @@ calloc (size_t nmemb, size_t size)
|
||||
res = user_data->calloc (nmemb, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C" char *
|
||||
strdup (const char *s)
|
||||
{
|
||||
char *p;
|
||||
size_t len = strlen (s) + 1;
|
||||
if ((p = (char *) malloc (len)) != NULL)
|
||||
memcpy (p, s, len);
|
||||
return p;
|
||||
}
|
||||
|
||||
extern "C" char *
|
||||
_strdup_r (struct _reent *, const char *s)
|
||||
{
|
||||
return strdup (s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* These routines are used by the application if it
|
||||
@ -178,22 +201,6 @@ export_calloc (size_t nmemb, size_t size)
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C" char *
|
||||
strdup (const char *s)
|
||||
{
|
||||
char *p;
|
||||
size_t len = strlen (s) + 1;
|
||||
if ((p = (char *) malloc (len)) != NULL)
|
||||
memcpy (p, s, len);
|
||||
return p;
|
||||
}
|
||||
|
||||
extern "C" char *
|
||||
_strdup_r (struct _reent *, const char *s)
|
||||
{
|
||||
return strdup (s);
|
||||
}
|
||||
|
||||
/* We use a critical section to lock access to the malloc data
|
||||
structures. This permits malloc to be called from different
|
||||
threads. Note that it does not make malloc reentrant, and it does
|
||||
|
@ -88,6 +88,7 @@ details. */
|
||||
#include "sync.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
|
||||
static int normalize_win32_path (const char *cwd, const char *src, char *dst);
|
||||
static char *getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot);
|
||||
@ -150,15 +151,71 @@ struct symlink_info
|
||||
/* Cache getcwd value. FIXME: We need a lock for these in order to
|
||||
support multiple threads. */
|
||||
|
||||
#ifdef _MT_SAFE
|
||||
#define cwd_win32 _reent_winsup()->_cwd_win32
|
||||
#define cwd_posix _reent_winsup()->_cwd_posix
|
||||
#define cwd_hash _reent_winsup()->_cwd_hash
|
||||
#else
|
||||
static char *cwd_win32;
|
||||
static char *cwd_posix;
|
||||
static unsigned long cwd_hash;
|
||||
#endif
|
||||
#define TMPCWD ((char *) alloca (MAX_PATH + 1))
|
||||
|
||||
struct cwdstuff
|
||||
{
|
||||
char *posix;
|
||||
char *win32;
|
||||
DWORD hash;
|
||||
muto *lock;
|
||||
};
|
||||
|
||||
cwdstuff cwd;
|
||||
|
||||
char * __stdcall
|
||||
cwd_win32 (char *buf)
|
||||
{
|
||||
char *ret;
|
||||
cwd.lock->acquire ();
|
||||
if (cwd.win32 == NULL)
|
||||
ret = NULL;
|
||||
else if (buf == NULL)
|
||||
ret = cwd.win32;
|
||||
else
|
||||
ret = strcpy (buf, cwd.win32);
|
||||
cwd.lock->release ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
char * __stdcall
|
||||
cwd_posix (char *buf)
|
||||
{
|
||||
char *ret;
|
||||
cwd.lock->acquire ();
|
||||
if (cwd.posix == NULL)
|
||||
ret = NULL;
|
||||
else if (buf == NULL)
|
||||
ret = cwd.posix;
|
||||
else
|
||||
ret = strcpy (buf, cwd.posix);
|
||||
cwd.lock->release ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DWORD __stdcall
|
||||
cwd_hash ()
|
||||
{
|
||||
DWORD hashnow;
|
||||
cwd.lock->acquire ();
|
||||
hashnow = cwd.hash;
|
||||
cwd.lock->release ();
|
||||
return hashnow;
|
||||
}
|
||||
|
||||
void __stdcall
|
||||
cwd_init ()
|
||||
{
|
||||
cwd.lock = new_muto (FALSE, "cwd");
|
||||
}
|
||||
|
||||
void __stdcall
|
||||
cwd_fixup_after_exec (char *win32, char *posix, DWORD hash)
|
||||
{
|
||||
cwd.win32 = win32;
|
||||
cwd.posix = posix;
|
||||
cwd.hash = hash;
|
||||
}
|
||||
|
||||
#define ischrootpath(path) \
|
||||
(myself->rootlen && \
|
||||
@ -965,7 +1022,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
|
||||
if (strpbrk (src_path, ":\\") != NULL)
|
||||
{
|
||||
debug_printf ("%s already win32", src_path);
|
||||
rc = normalize_win32_path (cwd_win32, src_path, dst);
|
||||
rc = normalize_win32_path (cwd_win32 (TMPCWD), src_path, dst);
|
||||
if (rc)
|
||||
{
|
||||
debug_printf ("normalize_win32_path failed, rc %d", rc);
|
||||
@ -1082,10 +1139,12 @@ fillin:
|
||||
/* Compute relative path if asked to and able to. */
|
||||
unsigned cwdlen;
|
||||
cwdlen = 0; /* avoid a (hopefully) bogus compiler warning */
|
||||
char *cwd_win32_now;
|
||||
cwd_win32_now = cwd_win32 (TMPCWD);
|
||||
if (win32_path == NULL)
|
||||
/* nothing to do */;
|
||||
else if (isrelpath &&
|
||||
path_prefix_p (cwd_win32, dst, cwdlen = strlen (cwd_win32)))
|
||||
path_prefix_p (cwd_win32_now, dst, cwdlen = strlen (cwd_win32_now)))
|
||||
{
|
||||
size_t n = strlen (dst);
|
||||
if (n < cwdlen)
|
||||
@ -1095,7 +1154,7 @@ fillin:
|
||||
if (n == cwdlen)
|
||||
dst += cwdlen;
|
||||
else
|
||||
dst += isdirsep (cwd_win32[cwdlen - 1]) ? cwdlen : cwdlen + 1;
|
||||
dst += isdirsep (cwd_win32_now[cwdlen - 1]) ? cwdlen : cwdlen + 1;
|
||||
|
||||
memmove (win32_path, dst, strlen (dst) + 1);
|
||||
if (!*win32_path)
|
||||
@ -2453,10 +2512,9 @@ hash_path_name (unsigned long hash, const char *name)
|
||||
Otherwise the inodes same will differ depending on whether a file is
|
||||
referenced with an absolute value or relatively. */
|
||||
|
||||
if (*name != '\\' && (cwd_win32 == NULL ||
|
||||
get_cwd_win32 ()))
|
||||
if (*name != '\\' && (cwd_win32 (TMPCWD) == NULL || get_cwd_win32 ()))
|
||||
{
|
||||
hash = cwd_hash;
|
||||
hash = cwd_hash ();
|
||||
if (name[0] == '.' && name[1] == '\0')
|
||||
return hash;
|
||||
hash = hash_path_name (hash, "\\");
|
||||
@ -2481,18 +2539,20 @@ get_cwd_win32 ()
|
||||
{
|
||||
DWORD dlen, len;
|
||||
|
||||
cwd.lock->acquire ();
|
||||
for (dlen = 256; ; dlen *= 2)
|
||||
{
|
||||
cwd_win32 = (char *) realloc (cwd_win32, dlen + 2);
|
||||
if ((len = GetCurrentDirectoryA (dlen, cwd_win32)) < dlen)
|
||||
cwd.win32 = (char *) crealloc (cwd.win32, dlen + 2);
|
||||
if ((len = GetCurrentDirectoryA (dlen, cwd.win32)) < dlen)
|
||||
break;
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
__seterrno ();
|
||||
else
|
||||
cwd_hash = hash_path_name (0, cwd_win32);
|
||||
cwd.hash = hash_path_name (0, cwd.win32);
|
||||
|
||||
cwd.lock->release ();
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -2504,16 +2564,18 @@ getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
|
||||
char *resbuf = NULL;
|
||||
size_t len = ulen;
|
||||
|
||||
if (cwd_win32 == NULL && !get_cwd_win32 ())
|
||||
if (cwd_win32 (TMPCWD) == NULL && !get_cwd_win32 ())
|
||||
return NULL;
|
||||
|
||||
char *cwd_win32_now = cwd_win32 (TMPCWD);
|
||||
char *cwd_posix_now = cwd_posix (TMPCWD);
|
||||
if (!posix_p)
|
||||
{
|
||||
if (strlen (cwd_win32) >= len)
|
||||
if (strlen (cwd_win32_now) >= len)
|
||||
set_errno (ERANGE);
|
||||
else
|
||||
{
|
||||
strcpy (buf, cwd_win32);
|
||||
strcpy (buf, cwd_win32_now);
|
||||
resbuf = buf;
|
||||
}
|
||||
|
||||
@ -2521,21 +2583,21 @@ getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
|
||||
resbuf, resbuf ? resbuf : "", buf, len);
|
||||
return resbuf;
|
||||
}
|
||||
else if (cwd_posix != NULL)
|
||||
else if (cwd_posix_now != NULL)
|
||||
{
|
||||
debug_printf("myself->root: %s, cwd_posix: %s", myself->root, cwd_posix);
|
||||
if (strlen (cwd_posix) >= len)
|
||||
debug_printf("myself->root: %s, cwd_posix: %s", myself->root, cwd_posix_now);
|
||||
if (strlen (cwd_posix_now) >= len)
|
||||
set_errno (ERANGE);
|
||||
else if (with_chroot && ischrootpath(cwd_posix))
|
||||
else if (with_chroot && ischrootpath(cwd_posix_now))
|
||||
{
|
||||
strcpy (buf, cwd_posix + myself->rootlen);
|
||||
strcpy (buf, cwd_posix_now + myself->rootlen);
|
||||
if (!buf[0])
|
||||
strcpy (buf, "/");
|
||||
resbuf = buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (buf, cwd_posix);
|
||||
strcpy (buf, cwd_posix_now);
|
||||
resbuf = buf;
|
||||
}
|
||||
|
||||
@ -2549,30 +2611,29 @@ getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
|
||||
char temp[MAX_PATH];
|
||||
|
||||
/* Turn from Win32 style to our style. */
|
||||
cygwin_shared->mount.conv_to_posix_path (cwd_win32, temp, 0);
|
||||
cygwin_shared->mount.conv_to_posix_path (cwd_win32_now, temp, 0);
|
||||
|
||||
size_t tlen = strlen (temp);
|
||||
|
||||
if (with_chroot && ischrootpath (temp))
|
||||
tlen -= myself->rootlen;
|
||||
|
||||
cwd_posix = (char *) realloc (
|
||||
cwd_posix, tlen + 1);
|
||||
if (cwd_posix != NULL)
|
||||
cwd.lock->acquire ();
|
||||
cwd.posix = (char *) crealloc (cwd.posix, tlen + 1);
|
||||
if (cwd.posix != NULL)
|
||||
if (with_chroot && ischrootpath (temp))
|
||||
{
|
||||
strcpy (cwd_posix, temp + myself->rootlen);
|
||||
strcpy (cwd.posix, temp + myself->rootlen);
|
||||
if (!buf[0])
|
||||
strcpy (buf, "/");
|
||||
}
|
||||
else
|
||||
strcpy (cwd_posix, temp);
|
||||
strcpy (cwd.posix, temp);
|
||||
|
||||
cwd.lock->release ();
|
||||
|
||||
if (tlen >= ulen)
|
||||
{
|
||||
/* len was too small */
|
||||
set_errno (ERANGE);
|
||||
}
|
||||
set_errno (ERANGE); /* len was too small */
|
||||
else
|
||||
{
|
||||
strcpy (buf, temp);
|
||||
@ -2643,12 +2704,13 @@ chdir (const char *dir)
|
||||
__seterrno ();
|
||||
else
|
||||
{
|
||||
cwd.lock->acquire ();
|
||||
/* Store new cache information */
|
||||
free (cwd_win32);
|
||||
cwd_win32 = strdup (path);
|
||||
cfree (cwd.win32);
|
||||
cwd.win32 = cstrdup (path);
|
||||
|
||||
char pathbuf[MAX_PATH];
|
||||
(void) normalize_posix_path (cwd_posix, dir, pathbuf);
|
||||
(void) normalize_posix_path (cwd.posix, dir, pathbuf);
|
||||
/* Look for trailing path component consisting entirely of dots. This
|
||||
is needed only in case of chdir since Windows simply ignores count
|
||||
of dots > 2 here instead of returning an error code. Counts of dots
|
||||
@ -2656,11 +2718,12 @@ chdir (const char *dir)
|
||||
char *last_slash = strrchr (pathbuf, '/');
|
||||
if (last_slash > pathbuf && strspn (last_slash + 1, ".") == strlen (last_slash + 1))
|
||||
*last_slash = '\0';
|
||||
free (cwd_posix);
|
||||
cwd_posix = strdup (pathbuf);
|
||||
cfree (cwd.posix);
|
||||
cwd.posix = cstrdup (pathbuf);
|
||||
cwd.lock->release ();
|
||||
}
|
||||
|
||||
syscall_printf ("%d = chdir() cwd_posix '%s' native '%s'", res, cwd_posix, native_dir);
|
||||
syscall_printf ("%d = chdir() cwd.posix '%s' native '%s'", res, cwd.posix, native_dir);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,11 @@ int __stdcall check_null_empty_path (const char *name);
|
||||
|
||||
const char * __stdcall find_exec (const char *name, path_conv& buf, const char *winenv = "PATH=",
|
||||
int null_if_notfound = 0, const char **known_suffix = NULL);
|
||||
void __stdcall cwd_init ();
|
||||
char * __stdcall cwd_posix (char *);
|
||||
char * __stdcall cwd_win32 (char *);
|
||||
DWORD __stdcall cwd_hash ();
|
||||
void __stdcall cwd_fixup_after_exec (char *, char *, DWORD);
|
||||
|
||||
/* Common macros for checking for invalid path names */
|
||||
|
||||
|
@ -68,24 +68,13 @@ set_myself (pid_t pid, HANDLE h)
|
||||
/* Initialize the process table entry for the current task.
|
||||
This is not called for fork'd tasks, only exec'd ones. */
|
||||
void __stdcall
|
||||
pinfo_init (LPBYTE info)
|
||||
pinfo_init (char **envp)
|
||||
{
|
||||
if (info != NULL)
|
||||
if (envp)
|
||||
{
|
||||
/* The process was execed. Reuse entry from the original
|
||||
owner of this pid. */
|
||||
environ_init (0); /* Needs myself but affects calls below */
|
||||
|
||||
environ_init (envp);
|
||||
/* spawn has already set up a pid structure for us so we'll use that */
|
||||
|
||||
myself->process_state |= PID_CYGPARENT;
|
||||
|
||||
/* Inherit file descriptor information from parent in info.
|
||||
*/
|
||||
LPBYTE b = fdtab.de_linearize_fd_array (info);
|
||||
extern char title_buf[];
|
||||
if (b && *b)
|
||||
old_title = strcpy (title_buf, (char *)b);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -97,7 +86,7 @@ pinfo_init (LPBYTE info)
|
||||
myself->ctty = -1;
|
||||
myself->uid = USHRT_MAX;
|
||||
|
||||
environ_init (0); /* call after myself has been set up */
|
||||
environ_init (NULL); /* call after myself has been set up */
|
||||
}
|
||||
|
||||
debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
|
||||
|
@ -163,6 +163,6 @@ cygwin_pid (pid_t pid)
|
||||
return (pid_t) (os_being_run == winNT) ? pid : -(int) pid;
|
||||
}
|
||||
|
||||
void __stdcall pinfo_init (BYTE *);
|
||||
void __stdcall pinfo_init (char **);
|
||||
void __stdcall set_myself (pid_t pid, HANDLE h = NULL);
|
||||
extern pinfo myself;
|
||||
|
@ -19,7 +19,6 @@ details. */
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <ctype.h>
|
||||
#include <paths.h>
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
#include "path.h"
|
||||
@ -28,10 +27,9 @@ details. */
|
||||
#include "sigproc.h"
|
||||
#include "child_info.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
#include "perthread.h"
|
||||
|
||||
extern BOOL allow_ntsec;
|
||||
|
||||
#define LINE_BUF_CHUNK (MAX_PATH * 2)
|
||||
|
||||
suffix_info std_suffixes[] =
|
||||
@ -171,7 +169,6 @@ handle (int n, int direction)
|
||||
*/
|
||||
|
||||
HANDLE NO_COPY hExeced = NULL;
|
||||
DWORD NO_COPY exec_exit = 0;
|
||||
|
||||
int
|
||||
iscmd (const char *argv0, const char *what)
|
||||
@ -242,19 +239,66 @@ exec_fixup_after_fork ()
|
||||
hexec_proc = NULL;
|
||||
}
|
||||
|
||||
struct av
|
||||
{
|
||||
int argc;
|
||||
int calloced;
|
||||
private:
|
||||
char **argv;
|
||||
public:
|
||||
av (int ac, const char * const *av) : argc (ac), calloced (0)
|
||||
{
|
||||
argv = (char **) cmalloc (HEAP_ARGV, (argc + 1) * sizeof (char *));
|
||||
memcpy (argv, av, (argc + 1) * sizeof (char *));
|
||||
}
|
||||
~av ()
|
||||
{
|
||||
for (int i = 0; i < calloced; i++)
|
||||
cfree (argv[i]);
|
||||
cfree (argv);
|
||||
}
|
||||
int unshift (const char *what, int conv = 0);
|
||||
operator char **() {return argv;}
|
||||
};
|
||||
|
||||
int
|
||||
av::unshift (const char *what, int conv)
|
||||
{
|
||||
char **av;
|
||||
av = (char **) crealloc (argv, (argc + 2) * sizeof (char *));
|
||||
if (!av)
|
||||
return 0;
|
||||
|
||||
argv = av;
|
||||
memmove (argv + 1, argv, (argc + 1) * sizeof (char *));
|
||||
char buf[MAX_PATH + 1];
|
||||
if (conv)
|
||||
{
|
||||
cygwin_conv_to_posix_path (what, buf);
|
||||
char *p = strchr (buf, '\0') - 4;
|
||||
if (p > buf && strcasematch (p, ".exe"))
|
||||
*p = '\0';
|
||||
what = buf;
|
||||
}
|
||||
*argv = cstrdup (what);
|
||||
argc++;
|
||||
calloced++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __stdcall
|
||||
spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
const char *const envp[], int mode)
|
||||
{
|
||||
int i;
|
||||
BOOL rc;
|
||||
int argc;
|
||||
pid_t cygpid;
|
||||
|
||||
hExeced = NULL;
|
||||
|
||||
MALLOC_CHECK;
|
||||
|
||||
// if (strstr (prog_arg, "dopath")) try_to_debug ();
|
||||
if (prog_arg == NULL)
|
||||
{
|
||||
syscall_printf ("prog_arg is NULL");
|
||||
@ -271,46 +315,69 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* CreateProcess takes one long string that is the command line (sigh).
|
||||
We need to quote any argument that has whitespace or embedded "'s. */
|
||||
|
||||
for (argc = 0; argv[argc]; argc++)
|
||||
/* nothing */;
|
||||
|
||||
char *real_path;
|
||||
path_conv real_path_buf;
|
||||
path_conv real_path;
|
||||
|
||||
linebuf one_line;
|
||||
|
||||
if (argc == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
|
||||
STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
|
||||
|
||||
child_info_spawn ciresrv;
|
||||
si.lpReserved2 = (LPBYTE) &ciresrv;
|
||||
si.cbReserved2 = sizeof (ciresrv);
|
||||
|
||||
HANDLE spr = NULL;
|
||||
DWORD chtype;
|
||||
if (mode != _P_OVERLAY && mode != _P_VFORK)
|
||||
chtype = PROC_SPAWN;
|
||||
else
|
||||
{
|
||||
spr = CreateEvent(&sec_all, TRUE, FALSE, NULL);
|
||||
ProtectHandle (spr);
|
||||
chtype = PROC_EXEC;
|
||||
}
|
||||
|
||||
init_child_info (chtype, &ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
|
||||
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &ciresrv.parent, 0, 1,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
system_printf ("couldn't create handle to myself for child, %E");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_EXEC, 1, sizeof (cygheap_exec_info));
|
||||
ciresrv.moreinfo->old_title = old_title ? cstrdup (old_title) : NULL;
|
||||
ciresrv.moreinfo->fds = fdtab;
|
||||
ciresrv.moreinfo->nfds = fdtab.size;
|
||||
|
||||
/* CreateProcess takes one long string that is the command line (sigh).
|
||||
We need to quote any argument that has whitespace or embedded "'s. */
|
||||
|
||||
int ac;
|
||||
for (ac = 0; argv[ac]; ac++)
|
||||
/* nothing */;
|
||||
|
||||
av newargv (ac, argv);
|
||||
|
||||
if (ac == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
|
||||
(iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
|
||||
{
|
||||
one_line.add (argv[0]);
|
||||
one_line.add (" ");
|
||||
one_line.add (argv[1]);
|
||||
one_line.add (" ");
|
||||
real_path = NULL;
|
||||
one_line.add (argv[2]);
|
||||
strcpy (real_path_buf, argv[0]);
|
||||
strcpy (real_path, argv[0]);
|
||||
goto skip_arg_parsing;
|
||||
}
|
||||
|
||||
real_path = real_path_buf;
|
||||
|
||||
const char *saved_prog_arg;
|
||||
const char *newargv0, **firstarg;
|
||||
const char *ext;
|
||||
|
||||
if ((ext = perhaps_suffix (prog_arg, real_path_buf)) == NULL)
|
||||
if ((ext = perhaps_suffix (prog_arg, real_path)) == NULL)
|
||||
{
|
||||
set_errno (ENOENT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
MALLOC_CHECK;
|
||||
saved_prog_arg = prog_arg;
|
||||
newargv0 = argv[0];
|
||||
firstarg = &newargv0;
|
||||
|
||||
/* If the file name ends in either .exe, .com, .bat, or .cmd we assume
|
||||
that it is NOT a script file */
|
||||
@ -351,8 +418,7 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
|
||||
if (buf[0] != '#' || buf[1] != '!')
|
||||
{
|
||||
strcpy (buf, "sh"); /* shell script without magic */
|
||||
pgm = buf;
|
||||
pgm = (char *) "/bin/sh";
|
||||
ptr = buf + 2;
|
||||
arg1 = NULL;
|
||||
}
|
||||
@ -379,55 +445,34 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
ptr = newptr - 1;
|
||||
}
|
||||
|
||||
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
char buf2[MAX_PATH + 1];
|
||||
|
||||
/* pointers:
|
||||
* pgm interpreter name
|
||||
* arg1 optional string
|
||||
* ptr end of string
|
||||
*/
|
||||
if (arg1)
|
||||
newargv.unshift (arg1);
|
||||
|
||||
if (!arg1)
|
||||
one_line.prepend (" ", 1);
|
||||
find_exec (pgm, real_path, "PATH=", 0, &ext);
|
||||
newargv.unshift (real_path, 1);
|
||||
}
|
||||
|
||||
if (real_path.iscygexec ())
|
||||
for (int i = newargv.calloced; i < newargv.argc; i++)
|
||||
newargv[i] = cstrdup (newargv[i]);
|
||||
else
|
||||
{
|
||||
one_line.prepend ("\" ", 2);
|
||||
one_line.prepend (arg1, strlen (arg1));
|
||||
one_line.prepend (" \"", 2);
|
||||
}
|
||||
|
||||
find_exec (pgm, real_path_buf, "PATH=", 0, &ext);
|
||||
cygwin_conv_to_posix_path (real_path, buf2);
|
||||
one_line.prepend (buf2, strlen (buf2));
|
||||
|
||||
/* If script had absolute path, add it to script name now!
|
||||
* This is necessary if script has been found via PATH.
|
||||
* For example, /usr/local/bin/tkman started as "tkman":
|
||||
* #!/usr/local/bin/wish -f
|
||||
* ...
|
||||
* We should run /usr/local/bin/wish -f /usr/local/bin/tkman,
|
||||
* but not /usr/local/bin/wish -f tkman!
|
||||
* We don't modify anything, if script has qulified path.
|
||||
*/
|
||||
if (firstarg)
|
||||
*firstarg = saved_prog_arg;
|
||||
|
||||
debug_printf ("prog_arg '%s', copy '%s'", prog_arg, one_line.buf);
|
||||
firstarg = NULL;
|
||||
}
|
||||
|
||||
for (; *argv; argv++)
|
||||
for (int i = 0; i < newargv.argc; i++)
|
||||
{
|
||||
char *p = NULL;
|
||||
const char *a = newargv0 ?: *argv;
|
||||
const char *a;
|
||||
|
||||
MALLOC_CHECK;
|
||||
|
||||
newargv0 = NULL;
|
||||
if (i >= newargv.calloced)
|
||||
newargv[i] = cstrdup (newargv[i]);
|
||||
a = newargv[i];
|
||||
int len = strlen (a);
|
||||
if (len != 0 && !strpbrk (a, " \t\n\r\""))
|
||||
one_line.add (a, len);
|
||||
@ -456,10 +501,28 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
else
|
||||
one_line.add ("", 1);
|
||||
MALLOC_CHECK;
|
||||
}
|
||||
ciresrv.moreinfo->argc = newargv.argc;
|
||||
ciresrv.moreinfo->argv = newargv;
|
||||
|
||||
/* FIXME: Should lock cwd access here. */
|
||||
ciresrv.moreinfo->cwd_posix = cwd_posix (NULL);
|
||||
ciresrv.moreinfo->cwd_win32 = cwd_win32 (NULL);
|
||||
ciresrv.moreinfo->cwd_hash = cwd_hash ();
|
||||
|
||||
ciresrv.moreinfo->environ = (char **) cmalloc (HEAP_ARGV, envsize (envp, 1));
|
||||
char **c;
|
||||
const char * const *e;
|
||||
for (c = ciresrv.moreinfo->environ, e = envp; *e; )
|
||||
*c++ = cstrdup (*e++);
|
||||
*c = NULL;
|
||||
if (mode != _P_OVERLAY ||
|
||||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc, &ciresrv.moreinfo->myself_pinfo, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
ciresrv.moreinfo->myself_pinfo = NULL;
|
||||
|
||||
skip_arg_parsing:
|
||||
PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
|
||||
STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
|
||||
si.lpReserved = NULL;
|
||||
si.lpDesktop = NULL;
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
@ -470,53 +533,7 @@ skip_arg_parsing:
|
||||
|
||||
/* Pass fd table to a child */
|
||||
|
||||
MALLOC_CHECK;
|
||||
int len = fdtab.linearize_fd_array (0, 0);
|
||||
MALLOC_CHECK;
|
||||
if (len == -1)
|
||||
{
|
||||
system_printf ("FATAL error in linearize_fd_array");
|
||||
return -1;
|
||||
}
|
||||
int titlelen = 1 + (old_title && mode == _P_OVERLAY ? strlen (old_title) : 0);
|
||||
si.cbReserved2 = len + titlelen + sizeof(child_info);
|
||||
si.lpReserved2 = (LPBYTE) alloca (si.cbReserved2);
|
||||
|
||||
# define ciresrv ((child_info *)si.lpReserved2)
|
||||
HANDLE spr = NULL;
|
||||
DWORD chtype;
|
||||
if (mode != _P_OVERLAY)
|
||||
chtype = PROC_SPAWN;
|
||||
else
|
||||
{
|
||||
spr = CreateEvent(&sec_all, TRUE, FALSE, NULL);
|
||||
ProtectHandle (spr);
|
||||
chtype = PROC_EXEC;
|
||||
}
|
||||
|
||||
init_child_info (chtype, ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
|
||||
if (mode != _P_OVERLAY ||
|
||||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
|
||||
&ciresrv->myself_pinfo, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
ciresrv->myself_pinfo = NULL;
|
||||
|
||||
LPBYTE resrv = si.lpReserved2 + sizeof *ciresrv;
|
||||
|
||||
if (fdtab.linearize_fd_array (resrv, len) < 0)
|
||||
{
|
||||
system_printf ("FATAL error in second linearize_fd_array");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (titlelen > 1)
|
||||
strcpy ((char *) resrv + len, old_title);
|
||||
else
|
||||
resrv[len] = '\0';
|
||||
|
||||
/* We print the translated program and arguments here so the user can see
|
||||
what was done to it. */
|
||||
syscall_printf ("spawn_guts (%s, %.132s)", real_path, one_line.buf);
|
||||
syscall_printf ("spawn_guts (%s, %.132s)", (char *) real_path, one_line.buf);
|
||||
|
||||
int flags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED |
|
||||
GetPriorityClass (hMainProc);
|
||||
@ -525,7 +542,14 @@ skip_arg_parsing:
|
||||
flags |= DETACHED_PROCESS;
|
||||
|
||||
/* Build windows style environment list */
|
||||
char *envblock = winenv (envp, 0);
|
||||
char *envblock;
|
||||
if (real_path.iscygexec ())
|
||||
envblock = NULL;
|
||||
else
|
||||
envblock = winenv (envp, 0);
|
||||
|
||||
ciresrv.cygheap = cygheap;
|
||||
ciresrv.cygheap_max = cygheap_max;
|
||||
|
||||
/* Preallocated buffer for `sec_user' call */
|
||||
char sa_buf[1024];
|
||||
@ -533,6 +557,9 @@ skip_arg_parsing:
|
||||
if (!hToken && myself->token != INVALID_HANDLE_VALUE)
|
||||
hToken = myself->token;
|
||||
|
||||
/* FIXME: This leaves a handle to the process open so that the pid is not
|
||||
duplicated. However, if a process execs another process two handles are
|
||||
left open, which is unnecessary. */
|
||||
if (mode == _P_OVERLAY && !hexec_proc &&
|
||||
!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
@ -594,7 +621,7 @@ skip_arg_parsing:
|
||||
&pi);
|
||||
/* Restore impersonation. In case of _P_OVERLAY this isn't
|
||||
allowed since it would overwrite child data. */
|
||||
if (mode != _P_OVERLAY
|
||||
if (mode != _P_OVERLAY && mode != _P_VFORK
|
||||
&& myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
|
||||
seteuid (uid);
|
||||
}
|
||||
@ -613,17 +640,13 @@ skip_arg_parsing:
|
||||
&pi);
|
||||
|
||||
MALLOC_CHECK;
|
||||
if (envblock)
|
||||
free (envblock);
|
||||
MALLOC_CHECK;
|
||||
|
||||
if (ciresrv->myself_pinfo)
|
||||
CloseHandle (ciresrv->myself_pinfo);
|
||||
|
||||
/* Set errno now so that debugging messages from it appear before our
|
||||
final debugging message [this is a general rule for debugging
|
||||
messages]. */
|
||||
if (!rc)
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
if (spr)
|
||||
@ -651,8 +674,8 @@ skip_arg_parsing:
|
||||
|
||||
if (mode == _P_OVERLAY)
|
||||
{
|
||||
close_all_files ();
|
||||
strcpy (myself->progname, real_path_buf);
|
||||
strcpy (myself->progname, real_path);
|
||||
// close_all_files ();
|
||||
proc_terminate ();
|
||||
hExeced = pi.hProcess;
|
||||
|
||||
@ -676,8 +699,6 @@ skip_arg_parsing:
|
||||
}
|
||||
child->username[0] = '\0';
|
||||
child->progname[0] = '\0';
|
||||
// CGF FIXME -- need to do this? strcpy (child->progname, path);
|
||||
// CGF FIXME -- need to do this? memcpy (child->username, myself->username, MAX_USER_NAME);
|
||||
child->ppid = myself->pid;
|
||||
child->uid = myself->uid;
|
||||
child->gid = myself->gid;
|
||||
@ -723,7 +744,7 @@ skip_arg_parsing:
|
||||
|
||||
DWORD res;
|
||||
|
||||
if (mode == _P_OVERLAY)
|
||||
if (mode == _P_OVERLAY || mode == _P_VFORK)
|
||||
{
|
||||
BOOL exited;
|
||||
|
||||
@ -732,33 +753,22 @@ skip_arg_parsing:
|
||||
|
||||
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
|
||||
res = 0;
|
||||
DWORD timeout = INFINITE;
|
||||
exec_exit = 1;
|
||||
exited = FALSE;
|
||||
MALLOC_CHECK;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, timeout))
|
||||
switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
|
||||
{
|
||||
case WAIT_TIMEOUT:
|
||||
syscall_printf ("WFMO timed out after signal");
|
||||
if (WaitForSingleObject (pi.hProcess, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
sigproc_printf ("subprocess still alive after signal");
|
||||
res = exec_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
sigproc_printf ("subprocess exited after signal");
|
||||
case WAIT_OBJECT_0:
|
||||
sigproc_printf ("subprocess exited");
|
||||
if (!GetExitCodeProcess (pi.hProcess, &res))
|
||||
res = exec_exit;
|
||||
res = 1;
|
||||
exited = TRUE;
|
||||
}
|
||||
if (nwait > 2)
|
||||
if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0)
|
||||
res |= EXIT_REPARENTING;
|
||||
|
||||
if (nwait <= 2 || mode != _P_OVERLAY)
|
||||
/* nothing to do */;
|
||||
else if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0)
|
||||
goto reparent;
|
||||
else if (!(res & EXIT_REPARENTING))
|
||||
{
|
||||
MALLOC_CHECK;
|
||||
@ -771,16 +781,18 @@ skip_arg_parsing:
|
||||
ResetEvent (signal_arrived);
|
||||
continue;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
res = EXIT_REPARENTING;
|
||||
MALLOC_CHECK;
|
||||
ForceCloseHandle (spr);
|
||||
MALLOC_CHECK;
|
||||
if (mode == _P_OVERLAY)
|
||||
{
|
||||
reparent:
|
||||
res |= EXIT_REPARENTING;
|
||||
close_all_files ();
|
||||
if (!parent_alive)
|
||||
{
|
||||
nwait = 1;
|
||||
sigproc_terminate ();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
DWORD r;
|
||||
@ -796,7 +808,6 @@ skip_arg_parsing:
|
||||
break;
|
||||
}
|
||||
|
||||
if (nwait > 2)
|
||||
ForceCloseHandle (spr);
|
||||
|
||||
sigproc_printf ("res = %x", res);
|
||||
@ -813,18 +824,19 @@ skip_arg_parsing:
|
||||
/* nothing */;
|
||||
else
|
||||
{
|
||||
int rc;
|
||||
HANDLE hP = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
|
||||
parent->dwProcessId);
|
||||
sigproc_printf ("parent handle %p, pid %d", hP, parent->dwProcessId);
|
||||
if (hP == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
|
||||
res = 1;
|
||||
rc = 1;
|
||||
else if (hP)
|
||||
{
|
||||
ProtectHandle (hP);
|
||||
res = DuplicateHandle (hMainProc, pi.hProcess, hP,
|
||||
rc = DuplicateHandle (hMainProc, pi.hProcess, hP,
|
||||
&myself->hProcess, 0, FALSE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
sigproc_printf ("Dup hP %d", res);
|
||||
sigproc_printf ("Dup hP %d", rc);
|
||||
ForceCloseHandle (hP);
|
||||
}
|
||||
if (!res)
|
||||
@ -837,7 +849,6 @@ skip_arg_parsing:
|
||||
system_printf ("myself->hProcess %x", myself->hProcess);
|
||||
}
|
||||
}
|
||||
res = EXIT_REPARENTING;
|
||||
ForceCloseHandle1 (hExeced, childhProc);
|
||||
hExeced = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
@ -848,15 +859,26 @@ skip_arg_parsing:
|
||||
}
|
||||
|
||||
MALLOC_CHECK;
|
||||
if (mode == _P_OVERLAY)
|
||||
do_exit (res | EXIT_NOCLOSEALL);
|
||||
}
|
||||
|
||||
if (mode == _P_WAIT)
|
||||
switch (mode)
|
||||
{
|
||||
case _P_WAIT:
|
||||
waitpid (cygpid, (int *) &res, 0);
|
||||
else if (mode == _P_DETACH)
|
||||
break;
|
||||
case _P_DETACH:
|
||||
res = 0; /* Lose all memory of this child. */
|
||||
else if ((mode == _P_NOWAIT) || (mode == _P_NOWAITO))
|
||||
break;
|
||||
case _P_NOWAIT:
|
||||
case _P_NOWAITO:
|
||||
case _P_VFORK:
|
||||
res = cygpid;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (int) res;
|
||||
}
|
||||
@ -896,12 +918,13 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
|
||||
/* Errno should be set by spawn_guts. */
|
||||
ret = -1;
|
||||
break;
|
||||
case _P_VFORK:
|
||||
case _P_NOWAIT:
|
||||
case _P_NOWAITO:
|
||||
case _P_WAIT:
|
||||
case _P_DETACH:
|
||||
subproc_init ();
|
||||
ret = spawn_guts (hToken, path, argv, envp, mode);
|
||||
ret = spawn_guts (hToken, path, argv, envp, 0);
|
||||
if (vf && ret > 0)
|
||||
{
|
||||
vf->pid = ret;
|
||||
|
@ -21,7 +21,6 @@ details. */
|
||||
#include <sys/uio.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <winnls.h>
|
||||
#include <lmcons.h> /* for UNLEN */
|
||||
#include "cygerrno.h"
|
||||
@ -32,6 +31,7 @@ details. */
|
||||
#include "sync.h"
|
||||
#include "sigproc.h"
|
||||
#include "pinfo.h"
|
||||
#include <unistd.h>
|
||||
|
||||
extern BOOL allow_ntsec;
|
||||
|
||||
@ -1015,8 +1015,8 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
|
||||
|
||||
debug_printf ("%s (%s, %p)", caller, name, buf);
|
||||
|
||||
path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL,
|
||||
stat_suffixes);
|
||||
path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) |
|
||||
PC_FULL, stat_suffixes);
|
||||
|
||||
if (real_path.error)
|
||||
{
|
||||
@ -1421,6 +1421,16 @@ pathconf (const char *file, int v)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" char *
|
||||
ttyname (int fd)
|
||||
{
|
||||
if (fdtab.not_open (fd) || !fdtab[fd]->is_tty ())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (char *)(fdtab[fd]->ttyname ());
|
||||
}
|
||||
|
||||
extern "C" char *
|
||||
ctermid (char *str)
|
||||
{
|
||||
@ -1434,20 +1444,8 @@ ctermid (char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
char *
|
||||
ttyname (int fd)
|
||||
{
|
||||
if (fdtab.not_open (fd) || !fdtab[fd]->is_tty ())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (char *)(fdtab[fd]->ttyname ());
|
||||
}
|
||||
|
||||
/* Tells stdio if it should do the cr/lf conversion for this file */
|
||||
extern "C" int _cygwin_istext_for_stdio (int fd);
|
||||
int
|
||||
extern "C" int
|
||||
_cygwin_istext_for_stdio (int fd)
|
||||
{
|
||||
syscall_printf("_cygwin_istext_for_stdio (%d)\n", fd);
|
||||
@ -1570,8 +1568,7 @@ setmode (int fd, int mode)
|
||||
}
|
||||
|
||||
/* ftruncate: P96 5.6.7.1 */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
ftruncate (int fd, off_t length)
|
||||
{
|
||||
int res = -1;
|
||||
@ -1609,8 +1606,7 @@ ftruncate (int fd, off_t length)
|
||||
|
||||
/* truncate: Provided by SVR4 and 4.3+BSD. Not part of POSIX.1 or XPG3 */
|
||||
/* FIXME: untested */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
truncate (const char *pathname, off_t length)
|
||||
{
|
||||
int fd;
|
||||
@ -1632,8 +1628,7 @@ truncate (const char *pathname, off_t length)
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
long
|
||||
extern "C" long
|
||||
get_osfhandle (int fd)
|
||||
{
|
||||
long res = -1;
|
||||
@ -1651,8 +1646,7 @@ get_osfhandle (int fd)
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
statfs (const char *fname, struct statfs *sfs)
|
||||
{
|
||||
if (!sfs)
|
||||
@ -1692,8 +1686,7 @@ statfs (const char *fname, struct statfs *sfs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
fstatfs (int fd, struct statfs *sfs)
|
||||
{
|
||||
if (fdtab.not_open (fd))
|
||||
@ -1706,8 +1699,7 @@ fstatfs (int fd, struct statfs *sfs)
|
||||
}
|
||||
|
||||
/* setpgid: POSIX 4.3.3.1 */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
setpgid (pid_t pid, pid_t pgid)
|
||||
{
|
||||
int res = -1;
|
||||
@ -1746,8 +1738,7 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
pid_t
|
||||
extern "C" pid_t
|
||||
getpgid (pid_t pid)
|
||||
{
|
||||
if (pid == 0)
|
||||
@ -1762,22 +1753,19 @@ getpgid (pid_t pid)
|
||||
return p->pgid;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
setpgrp (void)
|
||||
{
|
||||
return setpgid (0, 0);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
pid_t
|
||||
extern "C" pid_t
|
||||
getpgrp (void)
|
||||
{
|
||||
return getpgid (0);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
char *
|
||||
extern "C" char *
|
||||
ptsname (int fd)
|
||||
{
|
||||
if (fdtab.not_open (fd))
|
||||
@ -1789,8 +1777,7 @@ ptsname (int fd)
|
||||
}
|
||||
|
||||
/* FIXME: what is this? */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
regfree ()
|
||||
{
|
||||
return 0;
|
||||
@ -1802,8 +1789,7 @@ regfree ()
|
||||
Although mknod hasn't been implemented yet, some GNU tools (e.g. the
|
||||
fileutils) assume its existence so we must provide a stub that always
|
||||
fails. */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
mknod ()
|
||||
{
|
||||
set_errno (ENOSYS);
|
||||
@ -1811,8 +1797,7 @@ mknod ()
|
||||
}
|
||||
|
||||
/* setgid: POSIX 4.2.2.1 */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
setgid (gid_t gid)
|
||||
{
|
||||
int ret = setegid (gid);
|
||||
@ -1822,8 +1807,7 @@ setgid (gid_t gid)
|
||||
}
|
||||
|
||||
/* setuid: POSIX 4.2.2.1 */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
setuid (uid_t uid)
|
||||
{
|
||||
int ret = seteuid (uid);
|
||||
@ -1836,8 +1820,7 @@ setuid (uid_t uid)
|
||||
extern char *internal_getlogin (_pinfo *pi);
|
||||
|
||||
/* seteuid: standards? */
|
||||
extern "C"
|
||||
int
|
||||
extern "C" int
|
||||
seteuid (uid_t uid)
|
||||
{
|
||||
if (os_being_run == winNT)
|
||||
|
@ -74,9 +74,6 @@ struct _winsup_t
|
||||
|
||||
/* path.cc */
|
||||
struct mntent _ret;
|
||||
char *_cwd_win32;
|
||||
char *_cwd_posix;
|
||||
unsigned long _cwd_hash;
|
||||
int _iteration;
|
||||
|
||||
/* strerror */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* winsup.h: main Cygwin header file.
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||
Copyright 1996, 1997, 1998, 1999, 2000 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
@ -200,11 +200,7 @@ extern "C" int dll_noncygwin_dllcrt0 (HMODULE, per_process *);
|
||||
extern "C" void __stdcall do_exit (int) __attribute__ ((noreturn));
|
||||
|
||||
/* Initialize the environment */
|
||||
void environ_init (int);
|
||||
|
||||
/* Heap management. */
|
||||
void heap_init (void);
|
||||
void malloc_init (void);
|
||||
void environ_init (char **);
|
||||
|
||||
/* UID/GID */
|
||||
void uinfo_init (void);
|
||||
@ -258,6 +254,7 @@ extern "C" char *__stdcall rootdir (char *full_path);
|
||||
|
||||
void __stdcall mark (const char *, int);
|
||||
|
||||
#define _P_VFORK 0
|
||||
extern "C" int _spawnve (HANDLE hToken, int mode, const char *path,
|
||||
const char *const *argv, const char *const *envp);
|
||||
|
||||
@ -278,12 +275,6 @@ char *__stdcall strcasestr (const char *searchee, const char *lookfor);
|
||||
void __stdcall totimeval (struct timeval *dst, FILETIME * src, int sub, int flag);
|
||||
long __stdcall to_time_t (FILETIME * ptr);
|
||||
|
||||
/* pinfo table manipulation */
|
||||
#ifndef lock_pinfo_for_update
|
||||
int __stdcall lock_pinfo_for_update (DWORD timeout);
|
||||
#endif
|
||||
void unlock_pinfo (void);
|
||||
|
||||
/* Retrieve a security descriptor that allows all access */
|
||||
SECURITY_DESCRIPTOR *__stdcall get_null_sd (void);
|
||||
|
||||
@ -375,6 +366,7 @@ void __stdcall update_envptrs ();
|
||||
char * __stdcall winenv (const char * const *, int);
|
||||
extern char **__cygwin_environ, ***main_environ;
|
||||
extern "C" char __stdcall **cur_environ ();
|
||||
int __stdcall envsize (const char * const *, int debug_print = 0);
|
||||
|
||||
/* The title on program start. */
|
||||
extern char *old_title;
|
||||
|
Loading…
x
Reference in New Issue
Block a user