* 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:
Christopher Faylor 2000-09-03 04:16:35 +00:00
parent 39630fe3a1
commit b0e82b74fb
44 changed files with 2219 additions and 1888 deletions

View File

@ -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> 2000-09-02 Egor Duda <deo@logos-m.ru>
* Makefile.in: Remove "make check" support. It is now in * Makefile.in: Remove "make check" support. It is now in

View File

@ -50,7 +50,7 @@ DEFS = @DEFS@
CC:=@CC@ CC:=@CC@
# FIXME: Which is it, CC or CC_FOR_TARGET? # FIXME: Which is it, CC or CC_FOR_TARGET?
CC_FOR_TARGET:=$(CC) CC_FOR_TARGET:=$(CC)
CFLAGS:=@CFLAGS@ -MD CFLAGS:=@CFLAGS@ -MD -fno-implement-inlines
CXXFLAGS:=@CXXFLAGS@ CXXFLAGS:=@CXXFLAGS@
# For linking mount, etc. crt0.o isn't accessable in a fresh build. # 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_IMPORTS:=$(w32api_lib)/libkernel32.a
DLL_OFILES:=assert.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o dll_init.o \ DLL_OFILES:=assert.o cygheap.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o \
dtable.o environ.o errno.o exceptions.o exec.o external.o fcntl.o \ dll_init.o dtable.o environ.o errno.o exceptions.o exec.o external.o \
fhandler.o fhandler_console.o fhandler_floppy.o fhandler_random.o \ fcntl.o fhandler.o fhandler_console.o fhandler_floppy.o \
fhandler_raw.o fhandler_serial.o fhandler_tape.o fhandler_termios.o \ fhandler_random.o fhandler_raw.o fhandler_serial.o fhandler_tape.o \
fhandler_tty.o fhandler_windows.o fhandler_zero.o fork.o glob.o grp.o \ fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \
heap.o init.o ioctl.o localtime.o malloc.o mmap.o net.o ntea.o passwd.o \ fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o mmap.o \
path.o pinfo.o pipe.o poll.o regexp.o regerror.o regsub.o registry.o \ net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o regexp.o regerror.o \
resource.o scandir.o security.o select.o shared.o signal.o sigproc.o \ regsub.o registry.o resource.o scandir.o security.o select.o shared.o \
smallprint.o spawn.o strace.o strsep.o sync.o syscalls.o sysconf.o \ signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o sync.o \
syslog.o termios.o times.o tty.o uinfo.o uname.o wait.o window.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) $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MT_SAFE_OBJECTS)
GMON_OFILES:= gmon.o mcount.o profil.o GMON_OFILES:= gmon.o mcount.o profil.o

View File

@ -42,10 +42,10 @@ __assert (const char *file, int line, const char *failedexpr)
{ {
CloseHandle (h); CloseHandle (h);
small_printf ("assertion \"%s\" failed: file \"%s\", line %d\n", small_printf ("assertion \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line); failedexpr, file, line);
} }
abort (); abort (); // FIXME: Someday this should work.
/* NOTREACHED */ /* NOTREACHED */
} }

View File

@ -14,8 +14,9 @@ enum
PROC_FORK = PROC_MAGIC + 1, PROC_FORK = PROC_MAGIC + 1,
PROC_EXEC = PROC_MAGIC + 2, PROC_EXEC = PROC_MAGIC + 2,
PROC_SPAWN = PROC_MAGIC + 3, 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 // location information
PROC_SPAWN1 = PROC_MAGIC + 5
}; };
#define PROC_MAGIC_MASK 0xff00f000 #define PROC_MAGIC_MASK 0xff00f000
@ -34,12 +35,6 @@ public:
HANDLE shared_h; HANDLE shared_h;
HANDLE console_h; HANDLE console_h;
HANDLE parent_alive; // handle of thread used to track children 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 class child_info_fork: public child_info
@ -55,9 +50,53 @@ public:
void *stackbottom; // location of bottom of parent stack 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); void __stdcall init_child_info (DWORD, child_info *, int, HANDLE);
extern child_info_fork *child_proc_info; 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
View 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
View 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 *);
}

View File

@ -20,6 +20,8 @@ details. */
#include "sigproc.h" #include "sigproc.h"
#include "perthread.h" #include "perthread.h"
#include "pinfo.h" #include "pinfo.h"
#include "cygheap.h"
#include "heap.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "fhandler.h" #include "fhandler.h"
#include "child_info.h" #include "child_info.h"
@ -121,7 +123,7 @@ do_global_ctors (void (**in_pfunc)(), int force)
if (!force) if (!force)
{ {
if (user_data->forkee || user_data->run_ctors_p) if (user_data->forkee || user_data->run_ctors_p)
return; // inherit constructed stuff from parent pid return; // inherit constructed stuff from parent pid
user_data->run_ctors_p = 1; user_data->run_ctors_p = 1;
} }
@ -293,58 +295,38 @@ quoted (char *cmd, int winshell)
char *p; char *p;
char quote = *cmd; char quote = *cmd;
/* If this is being run from a Windows shell then we have if (!winshell)
to preserve quotes for globify to play with later. */
if (winshell)
{ {
while (*++cmd) char *p;
if ((p = strchr (cmd, quote)) == NULL) strcpy (cmd, cmd + 1);
{ if ((p = strchr (cmd, quote)) != NULL)
cmd = strchr (cmd, '\0'); // no closing quote strcpy (p, p + 1);
break; return p + 1;
}
else if (p[1] == quote && p[-1] != '\\')
{
*p = '\\';
cmd = ++p; // a quoted quote
}
else
{
cmd = p + 1; // point to after end
break;
}
return cmd;
} }
/* When running as a child of a cygwin process, the quoted /* This must have been run from a Windows shell, so preserve
characters should have been placed here by spawn_guts, so quotes for globify to play with later. */
we'll just pinch them out of the command string unless while (*++cmd)
they're quoted with a preceding \ */ if ((p = strpbrk (cmd, "\\\"")) == NULL)
p = cmd + 1; {
while (*p) cmd = strchr (cmd, '\0'); // no closing quote
{ break;
if (*p == '\\' && p[1] == '\\') }
{ else if (quote == '\'')
strcpy (p, p + 1); continue;
p++; else if (*p == '\\')
} cmd = ++p;
else if (*p != quote) else if (p[1] == quote)
p++; {
else if (p[-1] == '\\') *p = '\\';
strcpy (p - 1, p); cmd = ++p; // a quoted quote
else if (p[1] == quote) }
{ else
strcpy (p, p + 1); {
p++; cmd = p + 1; // point to after end
} break;
else }
{ return cmd;
strcpy (p, p + 1);
break;
}
}
strcpy (cmd, cmd + 1);
return p - 1;
} }
/* Perform a glob on word if it contains wildcard characters. /* Perform a glob on word if it contains wildcard characters.
@ -494,7 +476,8 @@ build_argv (char *cmd, char **&argv, int &argc, int winshell)
} }
argv[argc] = NULL; argv[argc] = NULL;
debug_printf ("argv[%d] = '%s'\n", argc, argv[argc]);
debug_printf ("argc %d", argc);
} }
/* sanity and sync check */ /* sanity and sync check */
@ -532,22 +515,35 @@ check_sanity_and_sync (per_process *p)
} }
static NO_COPY STARTUPINFO si; 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; child_info_fork NO_COPY *child_proc_info = NULL;
static MEMORY_BASIC_INFORMATION sm; static MEMORY_BASIC_INFORMATION sm;
#define EBP 6 // __inline__ void
#define ESP 7 extern void
extern __inline__ void
alloc_stack_hard_way (child_info_fork *ci, volatile char *b) alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
{ {
void *new_stack_pointer; void *new_stack_pointer;
MEMORY_BASIC_INFORMATION m; MEMORY_BASIC_INFORMATION m;
void *newbase;
int newlen;
LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
bool noguard;
if (!VirtualAlloc (ci->stacktop, if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
(DWORD) ci->stackbottom - (DWORD) ci->stacktop, {
MEM_RESERVE, PAGE_NOACCESS)) 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", api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
ci->stacktop, ci->stackbottom); ci->stacktop, ci->stackbottom);
@ -559,11 +555,14 @@ alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
new_stack_pointer, ci->stacksize); new_stack_pointer, ci->stacksize);
if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m)) if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
api_fatal ("fork: couldn't get new stack info, %E"); api_fatal ("fork: couldn't get new stack info, %E");
m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1); if (!noguard)
if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT, {
PAGE_EXECUTE_READWRITE|PAGE_GUARD)) m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
api_fatal ("fork: couldn't allocate new stack guard page %p, %E", if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
m.BaseAddress); 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)) if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
api_fatal ("fork: couldn't get new stack info, %E"); api_fatal ("fork: couldn't get new stack info, %E");
ci->stacktop = m.BaseAddress; 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 */ /* extend the stack prior to fork longjmp */
extern __inline__ void static void
alloc_stack (child_info_fork *ci) alloc_stack (child_info_fork *ci)
{ {
/* FIXME: adding 16384 seems to avoid a stack copy problem during /* FIXME: adding 16384 seems to avoid a stack copy problem during
@ -595,12 +594,9 @@ alloc_stack (child_info_fork *ci)
return; 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 NO_COPY int mypid = 0;
static int argc = 0; int _declspec(dllexport) __argc = 0;
static char **argv = NULL; char _declspec(dllexport) **__argv = NULL;
void void
sigthread::init (const char *s) sigthread::init (const char *s)
@ -616,22 +612,20 @@ sigthread::init (const char *s)
static void static void
dll_crt0_1 () dll_crt0_1 ()
{ {
#ifdef DEBUGGING /* According to onno@stack.urc.tue.nl, the exception handler record must
if (child_proc_info) be on the stack. */
switch (child_proc_info->type) /* FIXME: Verify forked children get their exception handler set up ok. */
{ exception_list cygwin_except_entry;
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
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); check_sanity_and_sync (user_data);
/* Nasty static stuff needed by newlib -- point to a local copy of /* Nasty static stuff needed by newlib -- point to a local copy of
@ -642,10 +636,58 @@ dll_crt0_1 ()
_impure_ptr = &reent_data; _impure_ptr = &reent_data;
#ifdef _MT_SAFE user_data->resourcelocks->Init ();
user_data->resourcelocks->Init(); user_data->threadinterface->Init0 ();
user_data->threadinterface->Init0(); regthread ("main", GetCurrentThreadId ());
#endif
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. */ /* Initialize the host dependent constants object. */
host_dependent.init (); host_dependent.init ();
@ -657,9 +699,6 @@ dll_crt0_1 ()
mainthread.init ("mainthread"); // For use in determining if signals mainthread.init ("mainthread"); // For use in determining if signals
// should be blocked. // should be blocked.
if (mypid)
set_myself ((pid_t) mypid, NULL);
(void) SetErrorMode (SEM_FAILCRITICALERRORS); (void) SetErrorMode (SEM_FAILCRITICALERRORS);
/* Initialize the heap. */ /* Initialize the heap. */
@ -684,18 +723,20 @@ dll_crt0_1 ()
NOTE: Don't do anything that involves the stack until you've completed NOTE: Don't do anything that involves the stack until you've completed
this step. */ this step. */
if (ciresrv->stacksize) if (fork_info->stacksize)
{ {
asm ("movl %0,%%fs:4" : : "r" (ciresrv->stackbottom)); asm ("movl %0,%%fs:4" : : "r" (fork_info->stackbottom));
asm ("movl %0,%%fs:8" : : "r" (ciresrv->stacktop)); 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 cygheap_init (); /* Initialize cygwin's heap */
dynamically loaded case. */ cwd_init ();
pinfo_init ((dynamically_loaded) ? NULL : info);
/* Initialize our process table entry. */
pinfo_init (envp);
if (!old_title && GetConsoleTitle (title_buf, TITLESIZE)) if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
old_title = title_buf; old_title = title_buf;
@ -740,26 +781,32 @@ dll_crt0_1 ()
/* Set up standard fds in file descriptor table. */ /* Set up standard fds in file descriptor table. */
stdio_init (); stdio_init ();
if (user_data->premain[0]) if (!__argc)
for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
user_data->premain[i] (argc, argv);
/* Scan the command line and build argv. Expand wildcards if not
called from another cygwin process. */
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], '\\')))
{ {
char *new_argv0 = (char *) alloca (MAX_PATH); /* Scan the command line and build argv. Expand wildcards if not
cygwin_conv_to_posix_path (argv[0], new_argv0); called from another cygwin process. */
argv[0] = new_argv0; 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], '\\')))
{
char *new_argv0 = (char *) alloca (MAX_PATH);
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. */ /* Set up __progname for getopt error call. */
__progname = argv[0]; __progname = __argv[0];
cygwin_finished_initializing = 1; cygwin_finished_initializing = 1;
/* Call init of loaded dlls. */ /* Call init of loaded dlls. */
@ -768,7 +815,7 @@ dll_crt0_1 ()
/* Execute any specified "premain" functions */ /* Execute any specified "premain" functions */
if (user_data->premain[PREMAIN_LEN / 2]) if (user_data->premain[PREMAIN_LEN / 2])
for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++) 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); debug_printf ("user_data->main %p", user_data->main);
@ -785,8 +832,9 @@ dll_crt0_1 ()
set_errno (0); set_errno (0);
MALLOC_CHECK;
if (user_data->main) 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 /* Wrap the real one, otherwise gdb gets confused about
@ -798,16 +846,7 @@ dll_crt0_1 ()
extern "C" void __stdcall extern "C" void __stdcall
_dll_crt0 () _dll_crt0 ()
{ {
char zeros[sizeof (ciresrv->zero)] = {0}; char zeros[sizeof (fork_info->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);
/* Set the os_being_run global. */ /* Set the os_being_run global. */
set_os_type (); set_os_type ();
@ -833,62 +872,35 @@ _dll_crt0 ()
DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc, DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
&hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS); &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
HANDLE h;
GetStartupInfo (&si); GetStartupInfo (&si);
if (si.cbReserved2 >= EXEC_MAGIC_SIZE && 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_EXEC:
case PROC_SPAWN: case PROC_SPAWN:
case PROC_FORK: case PROC_FORK:
case PROC_FORK1: case PROC_FORK1:
{ {
HANDLE me = hMainProc; child_proc_info = fork_info;
child_proc_info = ciresrv;
mypid = child_proc_info->cygpid; mypid = child_proc_info->cygpid;
cygwin_shared_h = child_proc_info->shared_h; cygwin_shared_h = child_proc_info->shared_h;
console_shared_h = child_proc_info->console_h; console_shared_h = child_proc_info->console_h;
/* We don't want subprocesses to inherit this */ /* We don't want subprocesses to inherit this */
if (!dynamically_loaded) if (dynamically_loaded)
{ parent_alive = NULL;
if (!DuplicateHandle (me, child_proc_info->parent_alive, else if (!DuplicateHandle (hMainProc, child_proc_info->parent_alive,
me, &parent_alive, 0, 0, hMainProc, &parent_alive, 0, 0,
DUPLICATE_SAME_ACCESS DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE)) | DUPLICATE_CLOSE_SOURCE))
system_printf ("parent_alive DuplicateHandle failed, %E"); 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; break;
} }
default: 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"); 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 char **envp;
static int _fmode; 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; user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (), if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),

View File

@ -86,7 +86,7 @@ delqueue_list::process_queue ()
int res = GetLastError (); int res = GetLastError ();
empty = 0; empty = 0;
if (res == ERROR_SHARING_VIOLATION || if (res == ERROR_SHARING_VIOLATION ||
(os_being_run != winNT && res == ERROR_ACCESS_DENIED)) (os_being_run != winNT && res == ERROR_ACCESS_DENIED))
{ {
/* File still inuse, that's ok */ /* File still inuse, that's ok */
syscall_printf ("Still using %s", name[i]); syscall_printf ("Still using %s", name[i]);
@ -94,7 +94,7 @@ delqueue_list::process_queue ()
else else
{ {
syscall_printf ("Hmm, don't know what to do with '%s', %E", name[i]); syscall_printf ("Hmm, don't know what to do with '%s', %E", name[i]);
inuse[i] = 0; inuse[i] = 0;
} }
} }
} }

View File

@ -75,7 +75,7 @@ opendir (const char *dirname)
} }
if (stat (myself->rootlen ? dirname : real_dirname.get_win32 (), if (stat (myself->rootlen ? dirname : real_dirname.get_win32 (),
&statbuf) == -1) &statbuf) == -1)
goto failed; goto failed;
if (!(statbuf.st_mode & S_IFDIR)) if (!(statbuf.st_mode & S_IFDIR))
@ -296,7 +296,7 @@ mkdir (const char *dir, mode_t mode)
if (CreateDirectoryA (real_dir.get_win32 (), 0)) if (CreateDirectoryA (real_dir.get_win32 (), 0))
{ {
set_file_attribute (real_dir.has_acls (), real_dir.get_win32 (), set_file_attribute (real_dir.has_acls (), real_dir.get_win32 (),
S_IFDIR | ((mode & 0777) & ~myself->umask)); S_IFDIR | ((mode & 0777) & ~myself->umask));
res = 0; res = 0;
} }
else else
@ -324,18 +324,18 @@ rmdir (const char *dir)
if (RemoveDirectoryA (real_dir.get_win32 ())) if (RemoveDirectoryA (real_dir.get_win32 ()))
{ {
/* RemoveDirectory on a samba drive doesn't return an error if the /* RemoveDirectory on a samba drive doesn't return an error if the
directory can't be removed because it's not empty. Checking for directory can't be removed because it's not empty. Checking for
existence afterwards keeps us informed about success. */ existence afterwards keeps us informed about success. */
if (GetFileAttributesA (real_dir.get_win32 ()) != (DWORD) -1) if (GetFileAttributesA (real_dir.get_win32 ()) != (DWORD) -1)
set_errno (ENOTEMPTY); set_errno (ENOTEMPTY);
else else
res = 0; res = 0;
} }
else if (GetLastError() == ERROR_ACCESS_DENIED) else if (GetLastError() == ERROR_ACCESS_DENIED)
{ {
/* Under Windows 9X or on a samba share, ERROR_ACCESS_DENIED is /* Under Windows 9X or on a samba share, ERROR_ACCESS_DENIED is
returned if you try to remove a file. On 9X the same error is returned if you try to remove a file. On 9X the same error is
returned if you try to remove a non-empty directory. */ returned if you try to remove a non-empty directory. */
if (real_dir.file_attributes () != (DWORD) -1 && if (real_dir.file_attributes () != (DWORD) -1 &&
!(real_dir.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)) !(real_dir.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
set_errno (ENOTDIR); set_errno (ENOTDIR);

View File

@ -23,6 +23,7 @@ details. */
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.h" #include "pinfo.h"
#include "cygheap.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.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() /* Try to allocate more space for fd table. We can't call realloc()
here to preserve old table if memory allocation fails */ 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"); debug_printf ("calloc failed");
return 0; return 0;
@ -70,7 +71,7 @@ dtable::extend (int howmuch)
if (fds) if (fds)
{ {
memcpy (newfds, fds, size * sizeof (fds[0])); memcpy (newfds, fds, size * sizeof (fds[0]));
free (fds); cfree (fds);
} }
size = new_size; size = new_size;
@ -151,7 +152,7 @@ dtable::release (int fd)
{ {
if (!not_open (fd)) if (!not_open (fd))
{ {
delete (fds[fd]); delete fds[fd]; /* CGF FIXME */
fds[fd] = NULL; fds[fd] = NULL;
} }
} }
@ -240,7 +241,7 @@ fhandler_base *
dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit) dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit)
{ {
fhandler_base *fh; fhandler_base *fh;
void *buf = calloc (1, sizeof (fhandler_union) + 100); void *buf = ccalloc (HEAP_FHANDLER, 1, sizeof (fhandler_union) + 100);
dev &= FH_DEVMASK; dev &= FH_DEVMASK;
switch (dev) switch (dev)
@ -312,7 +313,7 @@ dtable::dup_worker (fhandler_base *oldfh)
newfh->set_io_handle (NULL); newfh->set_io_handle (NULL);
if (oldfh->dup (newfh)) if (oldfh->dup (newfh))
{ {
free (newfh); cfree (newfh);
newfh = NULL; newfh = NULL;
return NULL; return NULL;
} }
@ -351,18 +352,21 @@ dtable::dup2 (int oldfd, int newfd)
} }
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup"); 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) if ((size_t) newfd >= fdtab.size || newfd < 0)
{ {
syscall_printf ("new fd out of bounds: %d", newfd); syscall_printf ("new fd out of bounds: %d", newfd);
set_errno (EBADF); set_errno (EBADF);
goto done; 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)) if (!not_open (newfd))
_close (newfd); _close (newfd);
fds[newfd] = newfh; fds[newfd] = newfh;
@ -382,12 +386,12 @@ done:
select_record * select_record *
dtable::select_read (int fd, select_record *s) dtable::select_read (int fd, select_record *s)
{ {
if (fdtab.not_open (fd)) if (not_open (fd))
{ {
set_errno (EBADF); set_errno (EBADF);
return NULL; return NULL;
} }
fhandler_base *fh = fdtab[fd]; fhandler_base *fh = fds[fd];
s = fh->select_read (s); s = fh->select_read (s);
s->fd = fd; s->fd = fd;
s->fh = fh; s->fh = fh;
@ -399,12 +403,12 @@ dtable::select_read (int fd, select_record *s)
select_record * select_record *
dtable::select_write (int fd, select_record *s) dtable::select_write (int fd, select_record *s)
{ {
if (fdtab.not_open (fd)) if (not_open (fd))
{ {
set_errno (EBADF); set_errno (EBADF);
return NULL; return NULL;
} }
fhandler_base *fh = fdtab[fd]; fhandler_base *fh = fds[fd];
s = fh->select_write (s); s = fh->select_write (s);
s->fd = fd; s->fd = fd;
s->fh = fh; s->fh = fh;
@ -416,12 +420,12 @@ dtable::select_write (int fd, select_record *s)
select_record * select_record *
dtable::select_except (int fd, select_record *s) dtable::select_except (int fd, select_record *s)
{ {
if (fdtab.not_open (fd)) if (not_open (fd))
{ {
set_errno (EBADF); set_errno (EBADF);
return NULL; return NULL;
} }
fhandler_base *fh = fdtab[fd]; fhandler_base *fh = fds[fd];
s = fh->select_except (s); s = fh->select_except (s);
s->fd = fd; s->fd = fd;
s->fh = fh; s->fh = fh;
@ -430,151 +434,33 @@ dtable::select_except (int fd, select_record *s)
return s; return s;
} }
/* /* Function to walk the fd table after an exec and perform
* Function to take an existant dtable array per-fhandler type fixups. */
* and linearize it into a memory buffer. void
* If memory buffer is NULL, it returns the size dtable::fixup_after_exec (HANDLE parent, size_t sz, fhandler_base **f)
* of memory buffer needed to do the linearization.
* On error returns -1.
*/
int
dtable::linearize_fd_array (unsigned char *in_buf, int buflen)
{ {
/* If buf == NULL, just precalculate length */ size = sz;
if (in_buf == NULL) fds = f;
{ first_fd_for_open = 0;
buflen = sizeof (size_t); for (size_t i = 0; i < size; i++)
for (int i = 0, max_used_fd = -1; i < (int)size; i++) if (fds[i])
if (!not_open (i) && !fds[i]->get_close_on_exec ()) if (fds[i]->get_close_on_exec ())
{ release (i);
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;
}
else else
{ {
len = fds[i]->linearize (buf); fds[i]->clear_readahead ();
debug_printf ("fd %d, len %d, name %s, device %p", i, len, buf, fds[i]->fixup_after_exec (parent);
fds[i]->get_device ());
} }
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 void
dtable::fixup_after_fork (HANDLE parent) dtable::fixup_after_fork (HANDLE parent)
{ {
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup"); SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
fhandler_base *fh;
for (size_t i = 0; i < size; i++) 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 ()) if (fh->get_close_on_exec () || fh->get_need_fork_fixup ())
{ {
debug_printf ("fd %d(%s)", i, fh->get_name ()); debug_printf ("fd %d(%s)", i, fh->get_name ());
@ -588,7 +474,7 @@ int
dtable::vfork_child_dup () dtable::vfork_child_dup ()
{ {
fhandler_base **newtable; fhandler_base **newtable;
newtable = (fhandler_base **) calloc (size, sizeof(fds[0])); newtable = (fhandler_base **) ccalloc (HEAP_ARGV, size, sizeof(fds[0]));
int res = 1; int res = 1;
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup"); SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
@ -601,6 +487,7 @@ dtable::vfork_child_dup ()
set_errno (EBADF); set_errno (EBADF);
goto out; goto out;
} }
fds_on_hold = fds; fds_on_hold = fds;
fds = newtable; fds = newtable;
out: out:
@ -617,7 +504,7 @@ dtable::vfork_parent_restore ()
fhandler_base **deleteme = fds; fhandler_base **deleteme = fds;
fds = fds_on_hold; fds = fds_on_hold;
fds_on_hold = NULL; fds_on_hold = NULL;
free (deleteme); cfree (deleteme);
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup"); ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
return; return;

View File

@ -30,8 +30,7 @@ public:
void release (int fd); void release (int fd);
void init_std_file_from_handle (int fd, HANDLE handle, DWORD access, const char *name); void init_std_file_from_handle (int fd, HANDLE handle, DWORD access, const char *name);
int dup2 (int oldfd, int newfd); int dup2 (int oldfd, int newfd);
int linearize_fd_array (unsigned char *buf, int buflen); void fixup_after_exec (HANDLE, size_t, fhandler_base **);
LPBYTE de_linearize_fd_array (LPBYTE buf);
fhandler_base *operator [](int fd) { return fds[fd]; } fhandler_base *operator [](int fd) { return fds[fd]; }
select_record *select_read (int fd, select_record *s); select_record *select_read (int fd, select_record *s);
select_record *select_write (int fd, select_record *s); select_record *select_write (int fd, select_record *s);

View File

@ -27,6 +27,8 @@ extern DWORD chunksize;
BOOL reset_com = TRUE; BOOL reset_com = TRUE;
static BOOL envcache = TRUE; static BOOL envcache = TRUE;
static char **lastenviron = NULL;
/* List of names which are converted from dos to unix /* List of names which are converted from dos to unix
* on the way in and back again on the way out. * 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. /* Convert windows path specs to POSIX, if appropriate.
*/ */
static void __stdcall static void __stdcall
posify (int already_posix, char **here, const char *value) posify (char **here, const char *value)
{ {
char *src = *here; char *src = *here;
win_env *conv; win_env *conv;
@ -111,22 +113,17 @@ posify (int already_posix, char **here, const char *value)
if (!(conv = getwinenv (src))) if (!(conv = getwinenv (src)))
return; return;
if (already_posix) /* Turn all the items from c:<foo>;<bar> into their
conv->add_cache (value, NULL); mounted equivalents - if there is one. */
else
{
/* Turn all the items from c:<foo>;<bar> into their
mounted equivalents - if there is one. */
char *outenv = (char *) malloc (1 + len + conv->posix_len (value)); char *outenv = (char *) malloc (1 + len + conv->posix_len (value));
memcpy (outenv, src, len); memcpy (outenv, src, len);
conv->toposix (value, outenv + len); conv->toposix (value, outenv + len);
conv->add_cache (outenv + len, value); conv->add_cache (outenv + len, value);
debug_printf ("env var converted to %s", outenv); debug_printf ("env var converted to %s", outenv);
*here = outenv; *here = outenv;
free (src); free (src);
}
} }
/* /*
@ -175,6 +172,16 @@ getenv (const char *name)
return my_findenv (name, &offset); 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 /* Takes similar arguments to setenv except that overwrite is
either -1, 0, or 1. 0 or 1 signify that the function should either -1, 0, or 1. 0 or 1 signify that the function should
perform similarly to setenv. Otherwise putenv is assumed. */ perform similarly to setenv. Otherwise putenv is assumed. */
@ -202,17 +209,19 @@ _addenv (const char *name, const char *value, int overwrite)
} }
else else
{ /* Create new slot. */ { /* Create new slot. */
char **env; int sz = envsize (cur_environ ());
int allocsz = sz + sizeof (char *);
/* Search for the end of the environment. */ offset = (sz - 1) / sizeof (char *);
for (env = cur_environ (); *env; env++)
continue;
offset = env - cur_environ (); /* Number of elements currently in environ. */
/* Allocate space for additional element plus terminating NULL. */ /* Allocate space for additional element plus terminating NULL. */
__cygwin_environ = (char **) realloc (cur_environ (), (sizeof (char *) * if (__cygwin_environ == lastenviron)
(offset + 2))); 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) if (!__cygwin_environ)
return -1; /* Oops. No more memory. */ return -1; /* Oops. No more memory. */
@ -261,7 +270,7 @@ putenv (const char *str)
if ((res = check_null_empty_path (str))) if ((res = check_null_empty_path (str)))
{ {
if (res == ENOENT) if (res == ENOENT)
return 0; return 0;
set_errno (res); set_errno (res);
return -1; return -1;
} }
@ -292,7 +301,7 @@ setenv (const char *name, const char *value, int overwrite)
if ((res = check_null_empty_path (name))) if ((res = check_null_empty_path (name)))
{ {
if (res == ENOENT) if (res == ENOENT)
return 0; return 0;
set_errno (res); set_errno (res);
return -1; return -1;
} }
@ -503,18 +512,15 @@ regopt (const char *name)
* environment variable and set appropriate options from it. * environment variable and set appropriate options from it.
*/ */
void void
environ_init (int already_posix) environ_init (char **envp)
{ {
char *rawenv = GetEnvironmentStrings (); char *rawenv;
int envsize, i; int sz, i;
char *p; char *p;
char *newp, **envp; char *newp;
int sawTERM = 0; int sawTERM = 0;
static char cygterm[] = "TERM=cygwin"; static char cygterm[] = "TERM=cygwin";
/* Allocate space for environment + trailing NULL + CYGWIN env. */
envp = (char **) malloc ((4 + (envsize = 100)) * sizeof (char *));
regopt ("default"); regopt ("default");
if (myself->progname[0]) if (myself->progname[0])
regopt (myself->progname); regopt (myself->progname);
@ -525,6 +531,19 @@ environ_init (int already_posix)
allow_ntsec = TRUE; allow_ntsec = TRUE;
#endif #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 /* Current directory information is recorded as variables of the
form "=X:=X:\foo\bar; these must be changed into something legal form "=X:=X:\foo\bar; these must be changed into something legal
(we could just ignore them but maybe an application will (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++) for (i = 0, p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1, i++)
{ {
newp = strdup (p); newp = strdup (p);
if (i >= envsize) if (i >= sz)
envp = (char **) realloc (envp, (4 + (envsize += 100)) * envp = (char **) realloc (envp, (4 + (sz += 100)) *
sizeof (char *)); sizeof (char *));
envp[i] = newp; envp[i] = newp;
if (*newp == '=') if (*newp == '=')
@ -548,13 +567,16 @@ environ_init (int already_posix)
if (strncmp (newp, "CYGWIN=", sizeof("CYGWIN=") - 1) == 0) if (strncmp (newp, "CYGWIN=", sizeof("CYGWIN=") - 1) == 0)
parse_options (newp + sizeof("CYGWIN=") - 1); parse_options (newp + sizeof("CYGWIN=") - 1);
if (*eq) if (*eq)
posify (already_posix, envp + i, *++eq ? eq : --eq); posify (envp + i, *++eq ? eq : --eq);
debug_printf ("%s", envp[i]); debug_printf ("%s", envp[i]);
} }
if (!sawTERM) if (!sawTERM)
envp[i++] = cygterm; envp[i++] = cygterm;
envp[i] = NULL; envp[i] = NULL;
FreeEnvironmentStrings (rawenv);
out:
__cygwin_environ = envp; __cygwin_environ = envp;
update_envptrs (); update_envptrs ();
parse_options (NULL); parse_options (NULL);

View File

@ -13,6 +13,7 @@ details. */
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include "cygheap.h"
#include <string.h> #include <string.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "fhandler.h" #include "fhandler.h"
@ -26,12 +27,26 @@ struct __cygwin_perfile *perfile_table = NULL;
DWORD binmode = 0; 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 int
fhandler_base::puts_readahead (const char *s, size_t len = (size_t) -1) fhandler_base::puts_readahead (const char *s, size_t len = (size_t) -1)
{ {
int success = 1; int success = 1;
while ((*s || (len != (size_t) -1 && len--)) while ((*s || (len != (size_t) -1 && len--))
&& (success = put_readahead (*s++) > 0)) && (success = put_readahead (*s++) > 0))
continue; continue;
return success; return success;
} }
@ -137,16 +152,16 @@ fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit
if (!no_free_names ()) if (!no_free_names ())
{ {
if (unix_path_name_ != NULL && unix_path_name_ != fhandler_disk_dummy_name) 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) 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; unix_path_name_ = win32_path_name_ = NULL;
if (unix_path == NULL || !*unix_path) if (unix_path == NULL || !*unix_path)
return; return;
unix_path_name_ = strdup (unix_path); unix_path_name_ = cstrdup (unix_path);
if (unix_path_name_ == NULL) if (unix_path_name_ == NULL)
{ {
system_printf ("fatal error. strdup failed"); 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) if (win32_path)
win32_path_name_ = strdup (win32_path); win32_path_name_ = cstrdup (win32_path);
else else
{ {
const char *fmt = get_native_name (); 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); __small_sprintf (win32_path_name_, fmt, unit);
} }
@ -196,7 +211,7 @@ fhandler_base::raw_read (void *ptr, size_t ulen)
break; break;
default: default:
syscall_printf ("ReadFile %s failed, %E", unix_path_name_); syscall_printf ("ReadFile %s failed, %E", unix_path_name_);
__seterrno_from_win_error (errcode); __seterrno_from_win_error (errcode);
return -1; return -1;
break; break;
} }
@ -205,37 +220,6 @@ fhandler_base::raw_read (void *ptr, size_t ulen)
return bytes_read; 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 /* Cover function to WriteFile to provide Posix interface and semantics
(as much as possible). */ (as much as possible). */
int int
@ -954,11 +938,11 @@ fhandler_disk_file::fstat (struct stat *buf)
directory. This is used, to set S_ISVTX, if needed. */ directory. This is used, to set S_ISVTX, if needed. */
if (local.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (local.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
buf->st_mode |= S_IFDIR; buf->st_mode |= S_IFDIR;
if (! get_file_attribute (has_acls (), if (!get_file_attribute (has_acls (),
get_win32_name (), get_win32_name (),
&buf->st_mode, &buf->st_mode,
&buf->st_uid, &buf->st_uid,
&buf->st_gid)) &buf->st_gid))
{ {
/* If read-only attribute is set, modify ntsec return value */ /* If read-only attribute is set, modify ntsec return value */
if (local.dwFileAttributes & FILE_ATTRIBUTE_READONLY) if (local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
@ -979,7 +963,7 @@ fhandler_disk_file::fstat (struct stat *buf)
buf->st_mode = 0; buf->st_mode = 0;
buf->st_mode |= STD_RBITS; buf->st_mode |= STD_RBITS;
if (! (local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) if (!(local.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
buf->st_mode |= STD_WBITS; buf->st_mode |= STD_WBITS;
/* | S_IWGRP | S_IWOTH; we don't give write to group etc */ /* | S_IWGRP | S_IWOTH; we don't give write to group etc */
@ -1124,6 +1108,13 @@ fhandler_base::tcgetpgrp (void)
return -1; return -1;
} }
void
fhandler_base::operator delete (void *p)
{
cfree (p);
return;
}
/* Normal I/O constructor */ /* Normal I/O constructor */
fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit): fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit):
access_ (0), access_ (0),
@ -1157,10 +1148,12 @@ fhandler_base::~fhandler_base (void)
if (!no_free_names ()) if (!no_free_names ())
{ {
if (unix_path_name_ != NULL && unix_path_name_ != fhandler_disk_dummy_name) 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) 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; unix_path_name_ = win32_path_name_ = NULL;
} }

View File

@ -149,13 +149,7 @@ public:
void set_name (const char * unix_path, const char * win32_path = NULL, void set_name (const char * unix_path, const char * win32_path = NULL,
int unit = 0); int unit = 0);
virtual fhandler_base& operator =(fhandler_base &x) 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;
};
fhandler_base (DWORD dev, const char *name = 0, int unit = 0); fhandler_base (DWORD dev, const char *name = 0, int unit = 0);
virtual ~fhandler_base (); virtual ~fhandler_base ();
@ -243,7 +237,8 @@ public:
unsigned long get_namehash () { return namehash_; } unsigned long get_namehash () { return namehash_; }
virtual void hclose (HANDLE h) {CloseHandle (h);} 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 */ /* fixup fd possibly non-inherited handles after fork */
void fork_fixup (HANDLE parent, HANDLE &h, const char *name); 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_read (void *ptr, size_t ulen);
virtual int raw_write (const 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 void fixup_after_exec (HANDLE) {}
virtual int linearize (unsigned char *);
/* Function to de-linearize into a fd */
virtual int de_linearize (const char *, const char *, const char *);
/* Virtual accessor functions to hide the fact /* Virtual accessor functions to hide the fact
that some fd's have two handles. */ that some fd's have two handles. */
@ -307,6 +299,12 @@ public:
return windows_device_names[FHDEVN (status)]; return windows_device_names[FHDEVN (status)];
} }
virtual int bg_check (int) {return 1;} 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 class fhandler_socket: public fhandler_base
@ -377,9 +375,6 @@ protected:
public: public:
~fhandler_dev_raw (void); ~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 open (const char *path, int flags, mode_t mode = 0);
int close (void); int close (void);
@ -497,7 +492,7 @@ public:
void dump (); void dump ();
int is_tty () { return 1; } int is_tty () { return 1; }
void fixup_after_fork (HANDLE parent); 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 /* We maintain a pgrp so that tcsetpgrp and tcgetpgrp work, but we
don't use it for permissions checking. fhandler_tty_slave does 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_write (select_record *s);
select_record *select_except (select_record *s); select_record *select_except (select_record *s);
int ready_for_read (int fd, DWORD howlong, int ignra); 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 set_close_on_exec (int val);
void fixup_after_fork (HANDLE parent); void fixup_after_fork (HANDLE parent);
void set_input_state () void set_input_state ()
@ -712,7 +707,7 @@ public:
int init (int); int init (int);
int init_console (); int init_console ();
void fixup_after_fork (HANDLE parent); 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 class fhandler_dev_null: public fhandler_base

View File

@ -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 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */ details. */
/* FIXMES:
Should the constructor call tcinit() explicitly rather than having
it sprinkled throughout here? */
#include "winsup.h" #include "winsup.h"
#include <sys/termios.h> #include <sys/termios.h>
#include <stdio.h> #include <stdio.h>
@ -21,6 +17,7 @@ details. */
#include <unistd.h> #include <unistd.h>
#include <wingdi.h> #include <wingdi.h>
#include <winuser.h> #include <winuser.h>
#include <wincon.h>
#include <ctype.h> #include <ctype.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "fhandler.h" #include "fhandler.h"
@ -1404,11 +1401,9 @@ set_console_title (char *title)
debug_printf ("title '%s'", buf); debug_printf ("title '%s'", buf);
} }
int void
fhandler_console::de_linearize (const char *buf, const char *unix_name, fhandler_console::fixup_after_exec (HANDLE)
const char *win32_name)
{ {
int res = fhandler_base::de_linearize (buf, unix_name, win32_name);
HANDLE h = get_handle (); HANDLE h = get_handle ();
HANDLE oh = get_output_handle (); HANDLE oh = get_output_handle ();
@ -1432,5 +1427,5 @@ fhandler_console::de_linearize (const char *buf, const char *unix_name,
CloseHandle (h); CloseHandle (h);
CloseHandle (oh); CloseHandle (oh);
return res; return;
} }

View File

@ -20,7 +20,7 @@ details. */
#define URANDOM 9 #define URANDOM 9
#define PSEUDO_MULTIPLIER (6364136223846793005LL) #define PSEUDO_MULTIPLIER (6364136223846793005LL)
#define PSEUDO_SHIFTVAL (21) #define PSEUDO_SHIFTVAL (21)
fhandler_dev_random::fhandler_dev_random (const char *name, int nunit) fhandler_dev_random::fhandler_dev_random (const char *name, int nunit)
: fhandler_base (FH_RANDOM, name), : fhandler_base (FH_RANDOM, name),
@ -42,10 +42,10 @@ fhandler_dev_random::crypt_gen_random (void *ptr, size_t len)
{ {
if (!crypt_prov if (!crypt_prov
&& !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, && !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET) CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)
&& !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, && !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET
| CRYPT_NEWKEYSET)) | CRYPT_NEWKEYSET))
{ {
debug_printf ("%E = CryptAquireContext()"); debug_printf ("%E = CryptAquireContext()");
return FALSE; return FALSE;
@ -144,7 +144,7 @@ fhandler_dev_random::close (void)
{ {
if (crypt_prov) if (crypt_prov)
while (!CryptReleaseContext (crypt_prov, 0) while (!CryptReleaseContext (crypt_prov, 0)
&& GetLastError () == ERROR_BUSY) && GetLastError () == ERROR_BUSY)
Sleep(10); Sleep(10);
return 0; return 0;
} }

View File

@ -16,6 +16,7 @@
#include <cygwin/rdevio.h> #include <cygwin/rdevio.h>
#include <sys/mtio.h> #include <sys/mtio.h>
#include "cygheap.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h" #include "path.h"
@ -25,7 +26,7 @@
also related to the used tape device. */ also related to the used tape device. */
static BOOL write_file (HANDLE fh, const void *buf, DWORD to_write, static BOOL write_file (HANDLE fh, const void *buf, DWORD to_write,
DWORD *written, int *err) DWORD *written, int *err)
{ {
BOOL ret; BOOL ret;
@ -33,20 +34,20 @@ static BOOL write_file (HANDLE fh, const void *buf, DWORD to_write,
if (!(ret = WriteFile (fh, buf, to_write, written, 0))) if (!(ret = WriteFile (fh, buf, to_write, written, 0)))
{ {
if ((*err = GetLastError ()) == ERROR_MEDIA_CHANGED if ((*err = GetLastError ()) == ERROR_MEDIA_CHANGED
|| *err == ERROR_BUS_RESET) || *err == ERROR_BUS_RESET)
{ {
*err = 0; *err = 0;
if (!(ret = WriteFile (fh, buf, to_write, written, 0))) if (!(ret = WriteFile (fh, buf, to_write, written, 0)))
*err = GetLastError (); *err = GetLastError ();
} }
} }
syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)",
ret, *err, fh, buf, to_write, *written); ret, *err, fh, buf, to_write, *written);
return ret; return ret;
} }
static BOOL read_file (HANDLE fh, void *buf, DWORD to_read, static BOOL read_file (HANDLE fh, void *buf, DWORD to_read,
DWORD *read, int *err) DWORD *read, int *err)
{ {
BOOL ret; BOOL ret;
@ -54,15 +55,15 @@ static BOOL read_file (HANDLE fh, void *buf, DWORD to_read,
if (!(ret = ReadFile(fh, buf, to_read, read, 0))) if (!(ret = ReadFile(fh, buf, to_read, read, 0)))
{ {
if ((*err = GetLastError ()) == ERROR_MEDIA_CHANGED if ((*err = GetLastError ()) == ERROR_MEDIA_CHANGED
|| *err == ERROR_BUS_RESET) || *err == ERROR_BUS_RESET)
{ {
*err = 0; *err = 0;
if (!(ret = ReadFile (fh, buf, to_read, read, 0))) if (!(ret = ReadFile (fh, buf, to_read, read, 0)))
*err = GetLastError (); *err = GetLastError ();
} }
} }
syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)",
ret, *err, fh, buf, to_read, *read); ret, *err, fh, buf, to_read, *read);
return ret; return ret;
} }
@ -96,13 +97,13 @@ fhandler_dev_raw::writebuf (void)
memset (devbuf + devbufend, 0, devbufsiz - devbufend); memset (devbuf + devbufend, 0, devbufsiz - devbufend);
if (get_device () != FH_TAPE) if (get_device () != FH_TAPE)
to_write = ((devbufend - 1) / 512 + 1) * 512; to_write = ((devbufend - 1) / 512 + 1) * 512;
else if (varblkop) else if (varblkop)
to_write = devbufend; to_write = devbufend;
else else
to_write = devbufsiz; to_write = devbufsiz;
if (!write_file (get_handle (), devbuf, to_write, &written, &ret) if (!write_file (get_handle (), devbuf, to_write, &written, &ret)
&& is_eom (ret)) && is_eom (ret))
eom_detected = 1; eom_detected = 1;
if (written) if (written)
has_written = 1; has_written = 1;
@ -120,23 +121,11 @@ fhandler_dev_raw::fhandler_dev_raw (DWORD devtype, const char *name, int unit) :
fhandler_dev_raw::~fhandler_dev_raw (void) fhandler_dev_raw::~fhandler_dev_raw (void)
{ {
delete[]devbuf; if (devbufsiz >= 1L)
cfree (devbuf);
clear (); 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 int
fhandler_dev_raw::open (const char *path, int flags, mode_t) 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 (ret)
{ {
if (devbufsiz > 1L) if (devbufsiz > 1L)
devbuf = new char[devbufsiz]; devbuf = (char *) cmalloc (HEAP_BUF, devbufsiz);
} }
else else
devbufsiz = 0; devbufsiz = 0;
@ -174,9 +163,9 @@ fhandler_dev_raw::fstat (struct stat *buf)
memset (buf, 0, sizeof *buf); memset (buf, 0, sizeof *buf);
buf->st_mode = S_IFCHR | buf->st_mode = S_IFCHR |
S_IRUSR | S_IWUSR | S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH; S_IROTH | S_IWOTH;
buf->st_nlink = 1; buf->st_nlink = 1;
buf->st_blksize = devbuf ? devbufsiz : 1; buf->st_blksize = devbuf ? devbufsiz : 1;
buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff); buf->st_dev = buf->st_rdev = get_device () << 8 | (unit & 0xff);
@ -241,9 +230,9 @@ fhandler_dev_raw::raw_read (void *ptr, size_t ulen)
{ {
if (!varblkop && len >= devbufsiz) if (!varblkop && len >= devbufsiz)
{ {
if (get_device () == FH_TAPE) if (get_device () == FH_TAPE)
bytes_to_read = (len / devbufsiz) * devbufsiz; bytes_to_read = (len / devbufsiz) * devbufsiz;
else else
bytes_to_read = (len / 512) * 512; bytes_to_read = (len / 512) * 512;
tgt = (char *) ptr; tgt = (char *) ptr;
debug_printf ("read %d bytes direct from file",bytes_to_read); debug_printf ("read %d bytes direct from file",bytes_to_read);
@ -252,9 +241,9 @@ fhandler_dev_raw::raw_read (void *ptr, size_t ulen)
{ {
bytes_to_read = devbufsiz; bytes_to_read = devbufsiz;
tgt = devbuf; tgt = devbuf;
if (varblkop) if (varblkop)
debug_printf ("read variable bytes from file into buffer"); debug_printf ("read variable bytes from file into buffer");
else else
debug_printf ("read %d bytes from file into buffer", debug_printf ("read %d bytes from file into buffer",
bytes_to_read); bytes_to_read);
} }
@ -262,7 +251,7 @@ fhandler_dev_raw::raw_read (void *ptr, size_t ulen)
{ {
if (!is_eof (ret) && !is_eom (ret)) if (!is_eof (ret) && !is_eom (ret))
{ {
debug_printf ("return -1, set errno to EACCES"); debug_printf ("return -1, set errno to EACCES");
set_errno (EACCES); set_errno (EACCES);
return -1; return -1;
} }
@ -276,7 +265,7 @@ fhandler_dev_raw::raw_read (void *ptr, size_t ulen)
{ {
if (!bytes_read && is_eom (ret)) if (!bytes_read && is_eom (ret))
{ {
debug_printf ("return -1, set errno to ENOSPC"); debug_printf ("return -1, set errno to ENOSPC");
set_errno (ENOSPC); set_errno (ENOSPC);
return -1; return -1;
} }
@ -304,7 +293,7 @@ fhandler_dev_raw::raw_read (void *ptr, size_t ulen)
{ {
if (!is_eof (ret) && !is_eom (ret)) if (!is_eof (ret) && !is_eom (ret))
{ {
debug_printf ("return -1, set errno to EACCES"); debug_printf ("return -1, set errno to EACCES");
set_errno (EACCES); set_errno (EACCES);
return -1; return -1;
} }
@ -317,7 +306,7 @@ fhandler_dev_raw::raw_read (void *ptr, size_t ulen)
} }
else if (is_eom (ret)) else if (is_eom (ret))
{ {
debug_printf ("return -1, set errno to ENOSPC"); debug_printf ("return -1, set errno to ENOSPC");
set_errno (ENOSPC); set_errno (ENOSPC);
return -1; return -1;
} }
@ -352,7 +341,7 @@ fhandler_dev_raw::raw_write (const void *ptr, size_t len)
while (len > 0) while (len > 0)
{ {
if (!varblkop && if (!varblkop &&
(len < devbufsiz || devbufend > 0) && devbufend < devbufsiz) (len < devbufsiz || devbufend > 0) && devbufend < devbufsiz)
{ {
bytes_to_write = min (len, devbufsiz - devbufend); bytes_to_write = min (len, devbufsiz - devbufend);
memcpy (devbuf + devbufend, p, bytes_to_write); memcpy (devbuf + devbufend, p, bytes_to_write);
@ -456,7 +445,7 @@ fhandler_dev_raw::dup (fhandler_base *child)
fhc->devbufsiz = devbufsiz; fhc->devbufsiz = devbufsiz;
if (devbufsiz > 1L) if (devbufsiz > 1L)
{ {
fhc->devbuf = new char[devbufsiz]; fhc->devbuf = (char *) cmalloc (HEAP_BUF, devbufsiz);
memcpy (fhc->devbuf, devbuf, devbufend); memcpy (fhc->devbuf, devbuf, devbufend);
} }
fhc->devbufstart = devbufstart; fhc->devbufstart = devbufstart;
@ -499,12 +488,12 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
ret = ERROR_INVALID_PARAMETER; ret = ERROR_INVALID_PARAMETER;
else if (!devbuf || op->rd_parm != devbufsiz) 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) if (devbuf)
{ {
memcpy (buf, devbuf + devbufstart, devbufend - devbufstart); memcpy (buf, devbuf + devbufstart, devbufend - devbufstart);
devbufend -= devbufstart; devbufend -= devbufstart;
delete[]devbuf; cfree (devbuf);
} }
else else
devbufend = 0; devbufend = 0;

View File

@ -503,7 +503,7 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
state.Parity = NOPARITY; state.Parity = NOPARITY;
state.fBinary = TRUE; /* Binary transfer */ state.fBinary = TRUE; /* Binary transfer */
state.EofChar = 0; /* No end-of-data in binary mode */ state.EofChar = 0; /* No end-of-data in binary mode */
state.fNull = FALSE; /* Don't discard nulls in binary mode */ state.fNull = FALSE; /* Don't discard nulls in binary mode */
/* -------------- Parity errors ------------------ */ /* -------------- Parity errors ------------------ */
@ -867,14 +867,12 @@ fhandler_serial::fixup_after_fork (HANDLE parent)
debug_printf ("io_status.hEvent %p", io_status.hEvent); debug_printf ("io_status.hEvent %p", io_status.hEvent);
} }
int void
fhandler_serial::de_linearize (const char *buf, const char *unix_name, fhandler_serial::fixup_after_exec (HANDLE)
const char *win32_name)
{ {
int res = fhandler_base::de_linearize (buf, unix_name, win32_name);
overlapped_setup (); overlapped_setup ();
debug_printf ("io_status.hEvent %p", io_status.hEvent); debug_printf ("io_status.hEvent %p", io_status.hEvent);
return res; return;
} }
int int

View File

@ -80,12 +80,12 @@ fhandler_dev_tape::open (const char *path, int flags, mode_t)
struct mtpos pos; struct mtpos pos;
if (! ioctl (MTIOCGET, &get)) if (! ioctl (MTIOCGET, &get))
/* Tape drive supports and is set to variable block size. */ /* Tape drive supports and is set to variable block size. */
if (get.mt_dsreg == 0) if (get.mt_dsreg == 0)
devbufsiz = get.mt_maxblksize; devbufsiz = get.mt_maxblksize;
else else
devbufsiz = get.mt_dsreg; devbufsiz = get.mt_dsreg;
varblkop = get.mt_dsreg == 0; varblkop = get.mt_dsreg == 0;
if (devbufsiz > 1L) if (devbufsiz > 1L)
devbuf = new char [ devbufsiz ]; devbuf = new char [ devbufsiz ];
@ -324,36 +324,36 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
break; break;
} }
if ((op->mt_count == 0 if ((op->mt_count == 0
&& !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK)) && !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
|| (op->mt_count > 0 || (op->mt_count > 0
&& (op->mt_count < min || op->mt_count > max))) && (op->mt_count < min || op->mt_count > max)))
{ {
ret = ERROR_INVALID_PARAMETER; ret = ERROR_INVALID_PARAMETER;
break; break;
} }
if (devbuf && op->mt_count > 0 if (devbuf && op->mt_count > 0
&& (size_t) op->mt_count < devbufend - devbufstart) && (size_t) op->mt_count < devbufend - devbufstart)
{ {
ret = ERROR_MORE_DATA; ret = ERROR_MORE_DATA;
break; break;
} }
if (! (ret = tape_set_blocksize (op->mt_count))) if (! (ret = tape_set_blocksize (op->mt_count)))
{ {
size_t size = 0; size_t size = 0;
if (op->mt_count == 0) if (op->mt_count == 0)
{ {
struct mtget get; struct mtget get;
if ((ret = tape_status (&get)) != NO_ERROR) if ((ret = tape_status (&get)) != NO_ERROR)
break; break;
size = get.mt_maxblksize; size = get.mt_maxblksize;
ret = NO_ERROR; ret = NO_ERROR;
} }
char *buf = new char [ size ]; char *buf = new char [ size ];
if (!buf) if (!buf)
{ {
ret = ERROR_OUTOFMEMORY; ret = ERROR_OUTOFMEMORY;
break; break;
} }
if (devbuf) if (devbuf)
{ {
memcpy(buf,devbuf + devbufstart, devbufend - devbufstart); memcpy(buf,devbuf + devbufstart, devbufend - devbufstart);
@ -365,7 +365,7 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
devbufstart = 0; devbufstart = 0;
devbuf = buf; devbuf = buf;
devbufsiz = size; devbufsiz = size;
varblkop = op->mt_count == 0; varblkop = op->mt_count == 0;
} }
} }
break; break;

View File

@ -22,6 +22,7 @@ details. */
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.h" #include "pinfo.h"
#include "cygheap.h"
/* Tty master stuff */ /* Tty master stuff */
@ -433,7 +434,7 @@ fhandler_tty_slave::fhandler_tty_slave(int num, const char *name) :
ttynum = num; ttynum = num;
/* FIXME: This is wasteful. We should rewrite the set_name path to eliminate the /* FIXME: This is wasteful. We should rewrite the set_name path to eliminate the
need for double allocates. */ 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_); strcpy (unix_path_name_, win32_path_name_);
unix_path_name_[0] = unix_path_name_[4] = '/'; unix_path_name_[0] = unix_path_name_[4] = '/';
debug_printf ("unix '%s', win32 '%s'", unix_path_name_, win32_path_name_); 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); console->fixup_after_fork (child);
} }
int void
fhandler_tty_master::de_linearize (const char *buf, const char *unix_name, fhandler_tty_master::fixup_after_exec (HANDLE)
const char *win32_name)
{ {
int res = fhandler_base::de_linearize (buf, unix_name, win32_name);
console->close (); console->close ();
init_console (); init_console ();
return res; return;
} }
int int

View File

@ -22,6 +22,7 @@ details. */
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.h" #include "pinfo.h"
#include "cygheap.h"
#include "child_info.h" #include "child_info.h"
#include "perthread.h" #include "perthread.h"
@ -37,14 +38,14 @@ DWORD NO_COPY chunksize = 0;
void void
per_thread::set (void *s) per_thread::set (void *s)
{ {
if (s == PER_THREAD_FORK_CLEAR) if (s == PER_THREAD_FORK_CLEAR)
{ {
tls = TlsAlloc (); tls = TlsAlloc ();
s = NULL; s = NULL;
} }
TlsSetValue (get_tls (), s); TlsSetValue (get_tls (), s);
} }
static void static void
stack_base (child_info_fork &ch) stack_base (child_info_fork &ch)
@ -356,7 +357,7 @@ fork ()
hParent = NULL; hParent = NULL;
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1, if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
DUPLICATE_SAME_ACCESS)) DUPLICATE_SAME_ACCESS))
{ {
system_printf ("couldn't create handle to myself for child, %E"); system_printf ("couldn't create handle to myself for child, %E");
goto cleanup; goto cleanup;
@ -365,13 +366,13 @@ fork ()
/* Remove impersonation */ /* Remove impersonation */
uid_t uid = geteuid(); uid_t uid = geteuid();
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (myself->orig_uid); seteuid (myself->orig_uid);
char sa_buf[1024]; char sa_buf[1024];
rc = CreateProcessA (myself->progname, /* image to run */ rc = CreateProcessA (myself->progname, /* image to run */
myself->progname, /* what we send in arg0 */ myself->progname, /* what we send in arg0 */
allow_ntsec ? sec_user (sa_buf) : &sec_none_nih, allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
allow_ntsec ? sec_user (sa_buf) : &sec_none_nih, allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
TRUE, /* inherit handles from parent */ TRUE, /* inherit handles from parent */
c_flags, c_flags,
NULL, /* environment filled in later */ NULL, /* environment filled in later */
@ -388,9 +389,9 @@ fork ()
ForceCloseHandle(subproc_ready); ForceCloseHandle(subproc_ready);
ForceCloseHandle(forker_finished); ForceCloseHandle(forker_finished);
subproc_ready = forker_finished = NULL; subproc_ready = forker_finished = NULL;
/* Restore impersonation */ /* Restore impersonation */
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (uid); seteuid (uid);
return -1; return -1;
} }
@ -402,7 +403,7 @@ fork ()
/* Restore impersonation */ /* Restore impersonation */
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (uid); seteuid (uid);
ProtectHandle (pi.hThread); ProtectHandle (pi.hThread);
/* Protect the handle but name it similarly to the way it will /* Protect the handle but name it similarly to the way it will
@ -413,7 +414,7 @@ fork ()
if (last_fork_proc) if (last_fork_proc)
CloseHandle (last_fork_proc); CloseHandle (last_fork_proc);
if (!DuplicateHandle (hMainProc, pi.hProcess, hMainProc, &last_fork_proc, if (!DuplicateHandle (hMainProc, pi.hProcess, hMainProc, &last_fork_proc,
0, FALSE, DUPLICATE_SAME_ACCESS)) 0, FALSE, DUPLICATE_SAME_ACCESS))
system_printf ("couldn't create last_fork_proc, %E"); system_printf ("couldn't create last_fork_proc, %E");
} }
@ -528,15 +529,15 @@ fork ()
debug_printf ("pid %d, ppid %d", x, myself->ppid); debug_printf ("pid %d, ppid %d", x, myself->ppid);
/* Restore the inheritance state as in parent /* Restore the inheritance state as in parent
Don't call setuid here! The flags are already set. */ Don't call setuid here! The flags are already set. */
if (myself->impersonated) if (myself->impersonated)
{ {
debug_printf ("Impersonation of child, token: %d", myself->token); debug_printf ("Impersonation of child, token: %d", myself->token);
if (myself->token == INVALID_HANDLE_VALUE) if (myself->token == INVALID_HANDLE_VALUE)
RevertToSelf (); // probably not needed RevertToSelf (); // probably not needed
else if (!ImpersonateLoggedOnUser (myself->token)) else if (!ImpersonateLoggedOnUser (myself->token))
system_printf ("Impersonate for forked child failed: %E"); system_printf ("Impersonate for forked child failed: %E");
} }
sync_with_parent ("after longjmp.", TRUE); sync_with_parent ("after longjmp.", TRUE);
ProtectHandle (hParent); ProtectHandle (hParent);
@ -567,6 +568,7 @@ fork ()
MALLOC_CHECK; MALLOC_CHECK;
cygheap_fixup_in_child (hParent);
fdtab.fixup_after_fork (hParent); fdtab.fixup_after_fork (hParent);
signal_fixup_after_fork (); signal_fixup_after_fork ();
exec_fixup_after_fork (); exec_fixup_after_fork ();

View File

@ -14,12 +14,8 @@ details. */
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.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) #define assert(x)
static unsigned page_const = 0; static unsigned page_const = 0;

22
winsup/cygwin/heap.h Normal file
View 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 ())

View File

@ -29,7 +29,7 @@ WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load)
if (user_data->threadinterface) if (user_data->threadinterface)
{ {
if ( !TlsSetValue(user_data->threadinterface->reent_index, if ( !TlsSetValue(user_data->threadinterface->reent_index,
&user_data->threadinterface->reents)) &user_data->threadinterface->reents))
api_fatal("Sig proc MT init failed\n"); api_fatal("Sig proc MT init failed\n");
} }
break; break;

View File

@ -13,6 +13,9 @@ details. */
#include "winsup.h" #include "winsup.h"
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include "cygheap.h"
#include "heap.h"
#include "sync.h" #include "sync.h"
/* we provide these stubs to call into a user's /* we provide these stubs to call into a user's
@ -60,6 +63,8 @@ extern "C" void
_free_r (struct _reent *, void *p) _free_r (struct _reent *, void *p)
{ {
export_malloc_called = 1; export_malloc_called = 1;
assert (!incygheap (p));
assert (inheap (p));
free (p); free (p);
} }
#undef free #undef free
@ -68,6 +73,8 @@ extern "C" void *
_realloc_r (struct _reent *, void *p, size_t size) _realloc_r (struct _reent *, void *p, size_t size)
{ {
export_malloc_called = 1; export_malloc_called = 1;
assert (!incygheap (p));
assert (inheap (p));
return realloc (p, size); return realloc (p, size);
} }
#undef realloc #undef realloc
@ -122,6 +129,22 @@ calloc (size_t nmemb, size_t size)
res = user_data->calloc (nmemb, size); res = user_data->calloc (nmemb, size);
return res; 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 #endif
/* These routines are used by the application if it /* These routines are used by the application if it
@ -178,22 +201,6 @@ export_calloc (size_t nmemb, size_t size)
return res; 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 /* We use a critical section to lock access to the malloc data
structures. This permits malloc to be called from different structures. This permits malloc to be called from different
threads. Note that it does not make malloc reentrant, and it does threads. Note that it does not make malloc reentrant, and it does

View File

@ -210,7 +210,7 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t off)
{ {
set_errno (EBADF); set_errno (EBADF);
syscall_printf ("-1 = mmap(): EBADF"); syscall_printf ("-1 = mmap(): EBADF");
ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap"); ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap");
return (caddr_t) -1; return (caddr_t) -1;
} }
hFile = fdtab[fd]->get_handle (); hFile = fdtab[fd]->get_handle ();
@ -235,7 +235,7 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t off)
__seterrno (); __seterrno ();
syscall_printf ("-1 = mmap(): MapViewOfFileEx failed with %E"); syscall_printf ("-1 = mmap(): MapViewOfFileEx failed with %E");
CloseHandle (h); CloseHandle (h);
ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap"); ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap");
return (caddr_t) -1; return (caddr_t) -1;
} }
} }
@ -247,7 +247,7 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t off)
__seterrno (); __seterrno ();
syscall_printf ("-1 = mmap(): MapViewOfFile failed with %E"); syscall_printf ("-1 = mmap(): MapViewOfFile failed with %E");
CloseHandle (h); CloseHandle (h);
ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap"); ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap");
return (caddr_t) -1; return (caddr_t) -1;
} }
} }
@ -273,7 +273,7 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t off)
CloseHandle (h); CloseHandle (h);
set_errno (ENOMEM); set_errno (ENOMEM);
syscall_printf ("-1 = mmap(): ENOMEM"); syscall_printf ("-1 = mmap(): ENOMEM");
ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap"); ReleaseResourceLock(LOCK_MMAP_LIST,READ_LOCK|WRITE_LOCK," mmap");
return (caddr_t) -1; return (caddr_t) -1;
} }
l = mmapped_areas->add_list (l, fd); l = mmapped_areas->add_list (l, fd);
@ -327,7 +327,7 @@ munmap (caddr_t addr, size_t len)
/* Delete the entry. */ /* Delete the entry. */
l->erase (li); l->erase (li);
syscall_printf ("0 = munmap(): %x", addr); syscall_printf ("0 = munmap(): %x", addr);
ReleaseResourceLock(LOCK_MMAP_LIST,WRITE_LOCK|READ_LOCK," munmap"); ReleaseResourceLock(LOCK_MMAP_LIST,WRITE_LOCK|READ_LOCK," munmap");
return 0; return 0;
} }
} }

View File

@ -354,18 +354,18 @@ cygwin_socket (int af, int type, int protocol)
soc = socket (AF_INET, type, 0); soc = socket (AF_INET, type, 0);
if (soc == INVALID_SOCKET) if (soc == INVALID_SOCKET)
{ {
set_winsock_errno (); set_winsock_errno ();
goto done; goto done;
} }
soc = duplicate_socket (soc); soc = duplicate_socket (soc);
const char *name; const char *name;
if (af == AF_INET) if (af == AF_INET)
name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp"); name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp");
else else
name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket"); name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket");
fdsock (fd, name, soc); fdsock (fd, name, soc);
res = fd; res = fd;
@ -781,11 +781,11 @@ cygwin_bind (int fd, struct sockaddr *my_addr, int addrlen)
int len = sizeof sin; int len = sizeof sin;
int fd; int fd;
if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN) if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
{ {
set_errno (ENAMETOOLONG); set_errno (ENAMETOOLONG);
goto out; goto out;
} }
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_port = 0; sin.sin_port = 0;
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
@ -805,36 +805,36 @@ cygwin_bind (int fd, struct sockaddr *my_addr, int addrlen)
sin.sin_port = ntohs (sin.sin_port); sin.sin_port = ntohs (sin.sin_port);
debug_printf ("AF_UNIX: socket bound to port %u", sin.sin_port); debug_printf ("AF_UNIX: socket bound to port %u", sin.sin_port);
/* bind must fail if file system socket object already exists /* bind must fail if file system socket object already exists
so _open() is called with O_EXCL flag. */ so _open() is called with O_EXCL flag. */
fd = _open (un_addr->sun_path, fd = _open (un_addr->sun_path,
O_WRONLY | O_CREAT | O_EXCL | O_BINARY, O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
0); 0);
if (fd < 0) if (fd < 0)
{ {
if (get_errno () == EEXIST) if (get_errno () == EEXIST)
set_errno (EADDRINUSE); set_errno (EADDRINUSE);
goto out; goto out;
} }
char buf[sizeof (SOCKET_COOKIE) + 10]; char buf[sizeof (SOCKET_COOKIE) + 10];
__small_sprintf (buf, "%s%u", SOCKET_COOKIE, sin.sin_port); __small_sprintf (buf, "%s%u", SOCKET_COOKIE, sin.sin_port);
len = strlen (buf) + 1; len = strlen (buf) + 1;
/* Note that the terminating nul is written. */ /* Note that the terminating nul is written. */
if (_write (fd, buf, len) != len) if (_write (fd, buf, len) != len)
{ {
save_errno here; save_errno here;
_close (fd); _close (fd);
_unlink (un_addr->sun_path); _unlink (un_addr->sun_path);
} }
else else
{ {
_close (fd); _close (fd);
chmod (un_addr->sun_path, chmod (un_addr->sun_path,
(S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~myself->umask); (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~myself->umask);
res = 0; res = 0;
} }
#undef un_addr #undef un_addr
} }
else if (bind (sock->get_socket (), my_addr, addrlen)) else if (bind (sock->get_socket (), my_addr, addrlen))
@ -1032,7 +1032,7 @@ getdomainname (char *domain, int len)
* \Device\<Netcard>, where netcard is the name of the net device. * \Device\<Netcard>, where netcard is the name of the net device.
* Then look under: * Then look under:
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<NetCard>\ * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<NetCard>\
* Parameters\Tcpip * Parameters\Tcpip
* at the IPAddress, Subnetmask and DefaultGateway values for the * at the IPAddress, Subnetmask and DefaultGateway values for the
* required values. * required values.
* *
@ -1709,36 +1709,36 @@ fhandler_socket::ioctl (unsigned int cmd, void *p)
case SIOCGIFNETMASK: case SIOCGIFNETMASK:
case SIOCGIFADDR: case SIOCGIFADDR:
{ {
char buf[2048]; char buf[2048];
struct ifconf ifc; struct ifconf ifc;
ifc.ifc_len = sizeof(buf); ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf; ifc.ifc_buf = buf;
struct ifreq *ifrp; struct ifreq *ifrp;
struct ifreq *ifr = (struct ifreq *) p; struct ifreq *ifr = (struct ifreq *) p;
if (ifr == 0) if (ifr == 0)
{ {
debug_printf("ifr == NULL\n"); debug_printf("ifr == NULL\n");
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
res = get_ifconf (&ifc, cmd); res = get_ifconf (&ifc, cmd);
if (res) if (res)
{ {
debug_printf ("error in get_ifconf\n"); debug_printf ("error in get_ifconf\n");
break; break;
} }
debug_printf(" name: %s\n", ifr->ifr_name); debug_printf(" name: %s\n", ifr->ifr_name);
for (ifrp = ifc.ifc_req; for (ifrp = ifc.ifc_req;
(caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len; (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
++ifrp) ++ifrp)
{ {
debug_printf("testname: %s\n", ifrp->ifr_name); debug_printf("testname: %s\n", ifrp->ifr_name);
if (! strcmp (ifrp->ifr_name, ifr->ifr_name)) if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
{ {
switch (cmd) switch (cmd)
{ {
case SIOCGIFADDR: case SIOCGIFADDR:
ifr->ifr_addr = ifrp->ifr_addr; ifr->ifr_addr = ifrp->ifr_addr;
@ -1750,15 +1750,15 @@ fhandler_socket::ioctl (unsigned int cmd, void *p)
ifr->ifr_netmask = ifrp->ifr_netmask; ifr->ifr_netmask = ifrp->ifr_netmask;
break; break;
} }
break; break;
} }
} }
if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len) if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
break; break;
} }
case FIOASYNC: case FIOASYNC:
res = WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, res = WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO,

View File

@ -134,22 +134,22 @@ read_etc_passwd ()
} }
fclose (f); fclose (f);
passwd_state = loaded; passwd_state = loaded;
} }
else else
{ {
debug_printf ("Emulating /etc/passwd"); debug_printf ("Emulating /etc/passwd");
char user_name [ MAX_USER_NAME ]; char user_name [ MAX_USER_NAME ];
DWORD user_name_len = MAX_USER_NAME; DWORD user_name_len = MAX_USER_NAME;
if (! GetUserNameA (user_name, &user_name_len)) if (! GetUserNameA (user_name, &user_name_len))
{ {
strncpy (user_name, "Administrator", MAX_USER_NAME); strncpy (user_name, "Administrator", MAX_USER_NAME);
debug_printf ("Failed to get current user name. %E"); debug_printf ("Failed to get current user name. %E");
} }
snprintf (linebuf, sizeof (linebuf), "%s::%u:%u::%s:/bin/sh", user_name, snprintf (linebuf, sizeof (linebuf), "%s::%u:%u::%s:/bin/sh", user_name,
DEFAULT_UID, DEFAULT_GID, getenv ("HOME") ?: "/"); DEFAULT_UID, DEFAULT_GID, getenv ("HOME") ?: "/");
add_pwd_line (linebuf); add_pwd_line (linebuf);
passwd_state = emulated; passwd_state = emulated;
} }
} }
@ -164,7 +164,7 @@ search_for (uid_t uid, const char *name)
{ {
res = passwd_buf + i; res = passwd_buf + i;
if (res->pw_uid == DEFAULT_UID) if (res->pw_uid == DEFAULT_UID)
default_pw = res; default_pw = res;
/* on Windows NT user names are case-insensitive */ /* on Windows NT user names are case-insensitive */
if (name) if (name)
{ {

View File

@ -88,6 +88,7 @@ details. */
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.h" #include "pinfo.h"
#include "cygheap.h"
static int normalize_win32_path (const char *cwd, const char *src, char *dst); 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); 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 /* Cache getcwd value. FIXME: We need a lock for these in order to
support multiple threads. */ support multiple threads. */
#ifdef _MT_SAFE #define TMPCWD ((char *) alloca (MAX_PATH + 1))
#define cwd_win32 _reent_winsup()->_cwd_win32
#define cwd_posix _reent_winsup()->_cwd_posix struct cwdstuff
#define cwd_hash _reent_winsup()->_cwd_hash {
#else char *posix;
static char *cwd_win32; char *win32;
static char *cwd_posix; DWORD hash;
static unsigned long cwd_hash; muto *lock;
#endif };
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) \ #define ischrootpath(path) \
(myself->rootlen && \ (myself->rootlen && \
@ -965,7 +1022,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
if (strpbrk (src_path, ":\\") != NULL) if (strpbrk (src_path, ":\\") != NULL)
{ {
debug_printf ("%s already win32", src_path); 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) if (rc)
{ {
debug_printf ("normalize_win32_path failed, rc %d", rc); debug_printf ("normalize_win32_path failed, rc %d", rc);
@ -1082,10 +1139,12 @@ fillin:
/* Compute relative path if asked to and able to. */ /* Compute relative path if asked to and able to. */
unsigned cwdlen; unsigned cwdlen;
cwdlen = 0; /* avoid a (hopefully) bogus compiler warning */ cwdlen = 0; /* avoid a (hopefully) bogus compiler warning */
char *cwd_win32_now;
cwd_win32_now = cwd_win32 (TMPCWD);
if (win32_path == NULL) if (win32_path == NULL)
/* nothing to do */; /* nothing to do */;
else if (isrelpath && 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); size_t n = strlen (dst);
if (n < cwdlen) if (n < cwdlen)
@ -1095,7 +1154,7 @@ fillin:
if (n == cwdlen) if (n == cwdlen)
dst += cwdlen; dst += cwdlen;
else 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); memmove (win32_path, dst, strlen (dst) + 1);
if (!*win32_path) 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 Otherwise the inodes same will differ depending on whether a file is
referenced with an absolute value or relatively. */ referenced with an absolute value or relatively. */
if (*name != '\\' && (cwd_win32 == NULL || if (*name != '\\' && (cwd_win32 (TMPCWD) == NULL || get_cwd_win32 ()))
get_cwd_win32 ()))
{ {
hash = cwd_hash; hash = cwd_hash ();
if (name[0] == '.' && name[1] == '\0') if (name[0] == '.' && name[1] == '\0')
return hash; return hash;
hash = hash_path_name (hash, "\\"); hash = hash_path_name (hash, "\\");
@ -2481,18 +2539,20 @@ get_cwd_win32 ()
{ {
DWORD dlen, len; DWORD dlen, len;
cwd.lock->acquire ();
for (dlen = 256; ; dlen *= 2) for (dlen = 256; ; dlen *= 2)
{ {
cwd_win32 = (char *) realloc (cwd_win32, dlen + 2); cwd.win32 = (char *) crealloc (cwd.win32, dlen + 2);
if ((len = GetCurrentDirectoryA (dlen, cwd_win32)) < dlen) if ((len = GetCurrentDirectoryA (dlen, cwd.win32)) < dlen)
break; break;
} }
if (len == 0) if (len == 0)
__seterrno (); __seterrno ();
else else
cwd_hash = hash_path_name (0, cwd_win32); cwd.hash = hash_path_name (0, cwd.win32);
cwd.lock->release ();
return len; return len;
} }
@ -2504,16 +2564,18 @@ getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
char *resbuf = NULL; char *resbuf = NULL;
size_t len = ulen; size_t len = ulen;
if (cwd_win32 == NULL && !get_cwd_win32 ()) if (cwd_win32 (TMPCWD) == NULL && !get_cwd_win32 ())
return NULL; return NULL;
char *cwd_win32_now = cwd_win32 (TMPCWD);
char *cwd_posix_now = cwd_posix (TMPCWD);
if (!posix_p) if (!posix_p)
{ {
if (strlen (cwd_win32) >= len) if (strlen (cwd_win32_now) >= len)
set_errno (ERANGE); set_errno (ERANGE);
else else
{ {
strcpy (buf, cwd_win32); strcpy (buf, cwd_win32_now);
resbuf = buf; resbuf = buf;
} }
@ -2521,21 +2583,21 @@ getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
resbuf, resbuf ? resbuf : "", buf, len); resbuf, resbuf ? resbuf : "", buf, len);
return resbuf; 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); debug_printf("myself->root: %s, cwd_posix: %s", myself->root, cwd_posix_now);
if (strlen (cwd_posix) >= len) if (strlen (cwd_posix_now) >= len)
set_errno (ERANGE); 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]) if (!buf[0])
strcpy (buf, "/"); strcpy (buf, "/");
resbuf = buf; resbuf = buf;
} }
else else
{ {
strcpy (buf, cwd_posix); strcpy (buf, cwd_posix_now);
resbuf = buf; resbuf = buf;
} }
@ -2549,30 +2611,29 @@ getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
char temp[MAX_PATH]; char temp[MAX_PATH];
/* Turn from Win32 style to our style. */ /* 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); size_t tlen = strlen (temp);
if (with_chroot && ischrootpath (temp)) if (with_chroot && ischrootpath (temp))
tlen -= myself->rootlen; tlen -= myself->rootlen;
cwd_posix = (char *) realloc ( cwd.lock->acquire ();
cwd_posix, tlen + 1); cwd.posix = (char *) crealloc (cwd.posix, tlen + 1);
if (cwd_posix != NULL) if (cwd.posix != NULL)
if (with_chroot && ischrootpath (temp)) if (with_chroot && ischrootpath (temp))
{ {
strcpy (cwd_posix, temp + myself->rootlen); strcpy (cwd.posix, temp + myself->rootlen);
if (!buf[0]) if (!buf[0])
strcpy (buf, "/"); strcpy (buf, "/");
} }
else else
strcpy (cwd_posix, temp); strcpy (cwd.posix, temp);
cwd.lock->release ();
if (tlen >= ulen) if (tlen >= ulen)
{ set_errno (ERANGE); /* len was too small */
/* len was too small */
set_errno (ERANGE);
}
else else
{ {
strcpy (buf, temp); strcpy (buf, temp);
@ -2643,12 +2704,13 @@ chdir (const char *dir)
__seterrno (); __seterrno ();
else else
{ {
cwd.lock->acquire ();
/* Store new cache information */ /* Store new cache information */
free (cwd_win32); cfree (cwd.win32);
cwd_win32 = strdup (path); cwd.win32 = cstrdup (path);
char pathbuf[MAX_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 /* Look for trailing path component consisting entirely of dots. This
is needed only in case of chdir since Windows simply ignores count 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 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, '/'); char *last_slash = strrchr (pathbuf, '/');
if (last_slash > pathbuf && strspn (last_slash + 1, ".") == strlen (last_slash + 1)) if (last_slash > pathbuf && strspn (last_slash + 1, ".") == strlen (last_slash + 1))
*last_slash = '\0'; *last_slash = '\0';
free (cwd_posix); cfree (cwd.posix);
cwd_posix = strdup (pathbuf); 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; return res;
} }

View File

@ -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=", 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); 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 */ /* Common macros for checking for invalid path names */

View File

@ -68,24 +68,13 @@ set_myself (pid_t pid, HANDLE h)
/* Initialize the process table entry for the current task. /* Initialize the process table entry for the current task.
This is not called for fork'd tasks, only exec'd ones. */ This is not called for fork'd tasks, only exec'd ones. */
void __stdcall void __stdcall
pinfo_init (LPBYTE info) pinfo_init (char **envp)
{ {
if (info != NULL) if (envp)
{ {
/* The process was execed. Reuse entry from the original environ_init (envp);
owner of this pid. */
environ_init (0); /* Needs myself but affects calls below */
/* spawn has already set up a pid structure for us so we'll use that */ /* spawn has already set up a pid structure for us so we'll use that */
myself->process_state |= PID_CYGPARENT; 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 else
{ {
@ -97,7 +86,7 @@ pinfo_init (LPBYTE info)
myself->ctty = -1; myself->ctty = -1;
myself->uid = USHRT_MAX; 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); debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);

View File

@ -72,10 +72,10 @@ public:
to `set_impersonation_token()'. */ to `set_impersonation_token()'. */
HANDLE token; HANDLE token;
BOOL impersonated; BOOL impersonated;
uid_t orig_uid; /* Remains intact also after impersonation */ uid_t orig_uid; /* Remains intact also after impersonation */
uid_t orig_gid; /* Ditto */ uid_t orig_gid; /* Ditto */
uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */ uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */
gid_t real_gid; /* Ditto */ gid_t real_gid; /* Ditto */
/* Filled when chroot() is called by the process or one of it's parents. /* Filled when chroot() is called by the process or one of it's parents.
Saved without trailing backslash. */ Saved without trailing backslash. */
@ -163,6 +163,6 @@ cygwin_pid (pid_t pid)
return (pid_t) (os_being_run == winNT) ? pid : -(int) 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); void __stdcall set_myself (pid_t pid, HANDLE h = NULL);
extern pinfo myself; extern pinfo myself;

View File

@ -48,36 +48,36 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
for (unsigned int i = 0; i < nfds; ++i) for (unsigned int i = 0; i < nfds; ++i)
if (!fdtab.not_open (fds[i].fd)) if (!fdtab.not_open (fds[i].fd))
{ {
FD_SET (fds[i].fd, open_fds); FD_SET (fds[i].fd, open_fds);
if (fds[i].events & POLLIN) if (fds[i].events & POLLIN)
FD_SET (fds[i].fd, read_fds); FD_SET (fds[i].fd, read_fds);
if (fds[i].events & POLLOUT) if (fds[i].events & POLLOUT)
FD_SET (fds[i].fd, write_fds); FD_SET (fds[i].fd, write_fds);
if (fds[i].events & POLLPRI) if (fds[i].events & POLLPRI)
FD_SET (fds[i].fd, except_fds); FD_SET (fds[i].fd, except_fds);
} }
int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds, int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds,
timeout < 0 ? NULL : &tv); timeout < 0 ? NULL : &tv);
for (unsigned int i = 0; i < nfds; ++i) for (unsigned int i = 0; i < nfds; ++i)
{ {
if (!FD_ISSET (fds[i].fd, open_fds)) if (!FD_ISSET (fds[i].fd, open_fds))
fds[i].revents = POLLNVAL; fds[i].revents = POLLNVAL;
else if (fdtab.not_open(fds[i].fd)) else if (fdtab.not_open(fds[i].fd))
fds[i].revents = POLLHUP; fds[i].revents = POLLHUP;
else if (ret < 0) else if (ret < 0)
fds[i].revents = POLLERR; fds[i].revents = POLLERR;
else else
{ {
fds[i].revents = 0; fds[i].revents = 0;
if (FD_ISSET (fds[i].fd, read_fds)) if (FD_ISSET (fds[i].fd, read_fds))
fds[i].revents |= POLLIN; fds[i].revents |= POLLIN;
if (FD_ISSET (fds[i].fd, write_fds)) if (FD_ISSET (fds[i].fd, write_fds))
fds[i].revents |= POLLOUT; fds[i].revents |= POLLOUT;
if (FD_ISSET (fds[i].fd, except_fds)) if (FD_ISSET (fds[i].fd, except_fds))
fds[i].revents |= POLLPRI; fds[i].revents |= POLLPRI;
} }
} }
return ret; return ret;

View File

@ -208,11 +208,11 @@ get_registry_hive_path (const PSID psid, char *path)
key[0] = '\0'; key[0] = '\0';
if (!RegQueryValueExA (hkey, "ProfileImagePath", 0, &type, if (!RegQueryValueExA (hkey, "ProfileImagePath", 0, &type,
(BYTE *)buf, (siz = 256, &siz))) (BYTE *)buf, (siz = 256, &siz)))
ExpandEnvironmentStringsA (buf, key, 256); ExpandEnvironmentStringsA (buf, key, 256);
RegCloseKey (hkey); RegCloseKey (hkey);
if (key[0]) if (key[0])
return strcpy (path, key); return strcpy (path, key);
} }
return NULL; return NULL;
} }
@ -229,7 +229,7 @@ load_registry_hive (PSID psid)
return; return;
/* Check if user hive is already loaded. */ /* Check if user hive is already loaded. */
if (!RegOpenKeyExA (HKEY_USERS, convert_sid_to_string_sid (psid, sid), if (!RegOpenKeyExA (HKEY_USERS, convert_sid_to_string_sid (psid, sid),
0, KEY_READ, &hkey)) 0, KEY_READ, &hkey))
{ {
debug_printf ("User registry hive for %s already exists", sid); debug_printf ("User registry hive for %s already exists", sid);
RegCloseKey (hkey); RegCloseKey (hkey);
@ -239,7 +239,7 @@ load_registry_hive (PSID psid)
{ {
strcat (path, "\\NTUSER.DAT"); strcat (path, "\\NTUSER.DAT");
if ((ret = RegLoadKeyA (HKEY_USERS, sid, path)) != ERROR_SUCCESS) if ((ret = RegLoadKeyA (HKEY_USERS, sid, path)) != ERROR_SUCCESS)
debug_printf ("Loading user registry hive for %s failed: %d", sid, ret); debug_printf ("Loading user registry hive for %s failed: %d", sid, ret);
} }
} }

View File

@ -73,11 +73,11 @@ scandir (const char *dir,
{ {
closedir (dirp); closedir (dirp);
if (nl) if (nl)
{ {
while (count > 0) while (count > 0)
free (nl[--count]); free (nl[--count]);
free (nl); free (nl);
} }
/* Ignore errors from closedir() and what not else. */ /* Ignore errors from closedir() and what not else. */
set_errno (prior_errno); set_errno (prior_errno);
return -1; return -1;

File diff suppressed because it is too large Load Diff

View File

@ -841,10 +841,10 @@ peek_serial (select_record *s, int)
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
if (!ClearCommError (h, &ev, &st)) if (!ClearCommError (h, &ev, &st))
{ {
debug_printf ("ClearCommError"); debug_printf ("ClearCommError");
goto err; goto err;
} }
else if (!st.cbInQue) else if (!st.cbInQue)
Sleep (to); Sleep (to);
else else

View File

@ -209,7 +209,7 @@ sec_user (PVOID sa_buf, PSID sid2, BOOL inherit)
PSECURITY_ATTRIBUTES psa = (PSECURITY_ATTRIBUTES) sa_buf; PSECURITY_ATTRIBUTES psa = (PSECURITY_ATTRIBUTES) sa_buf;
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)
((char *) sa_buf + sizeof (*psa)); ((char *) sa_buf + sizeof (*psa));
PACL acl = (PACL) ((char *) sa_buf + sizeof (*psa) + sizeof (*psd)); PACL acl = (PACL) ((char *) sa_buf + sizeof (*psa) + sizeof (*psd));
char sid_buf[MAX_SID_LEN]; char sid_buf[MAX_SID_LEN];
@ -221,46 +221,46 @@ sec_user (PVOID sa_buf, PSID sid2, BOOL inherit)
return inherit ? &sec_none_nih : &sec_none; return inherit ? &sec_none_nih : &sec_none;
size_t acl_len = sizeof (ACL) size_t acl_len = sizeof (ACL)
+ 4 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)) + 4 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD))
+ GetLengthSid (sid) + GetLengthSid (sid)
+ GetLengthSid (get_admin_sid ()) + GetLengthSid (get_admin_sid ())
+ GetLengthSid (get_system_sid ()) + GetLengthSid (get_system_sid ())
+ GetLengthSid (get_creator_owner_sid ()); + GetLengthSid (get_creator_owner_sid ());
if (sid2) if (sid2)
acl_len += sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) acl_len += sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)
+ GetLengthSid (sid2); + GetLengthSid (sid2);
if (! InitializeAcl (acl, acl_len, ACL_REVISION)) if (! InitializeAcl (acl, acl_len, ACL_REVISION))
debug_printf("InitializeAcl %E"); debug_printf("InitializeAcl %E");
if (! AddAccessAllowedAce (acl, ACL_REVISION, if (! AddAccessAllowedAce (acl, ACL_REVISION,
SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
sid)) sid))
debug_printf("AddAccessAllowedAce(%s) %E", getlogin()); debug_printf("AddAccessAllowedAce(%s) %E", getlogin());
if (! AddAccessAllowedAce (acl, ACL_REVISION, if (! AddAccessAllowedAce (acl, ACL_REVISION,
SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
get_admin_sid ())) get_admin_sid ()))
debug_printf("AddAccessAllowedAce(admin) %E"); debug_printf("AddAccessAllowedAce(admin) %E");
if (! AddAccessAllowedAce (acl, ACL_REVISION, if (! AddAccessAllowedAce (acl, ACL_REVISION,
SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
get_system_sid ())) get_system_sid ()))
debug_printf("AddAccessAllowedAce(system) %E"); debug_printf("AddAccessAllowedAce(system) %E");
if (! AddAccessAllowedAce (acl, ACL_REVISION, if (! AddAccessAllowedAce (acl, ACL_REVISION,
SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
get_creator_owner_sid ())) get_creator_owner_sid ()))
debug_printf("AddAccessAllowedAce(creator_owner) %E"); debug_printf("AddAccessAllowedAce(creator_owner) %E");
if (sid2) if (sid2)
if (! AddAccessAllowedAce (acl, ACL_REVISION, if (! AddAccessAllowedAce (acl, ACL_REVISION,
SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
sid2)) sid2))
debug_printf("AddAccessAllowedAce(sid2) %E"); debug_printf("AddAccessAllowedAce(sid2) %E");
if (! InitializeSecurityDescriptor (psd, if (! InitializeSecurityDescriptor (psd,
SECURITY_DESCRIPTOR_REVISION)) SECURITY_DESCRIPTOR_REVISION))
debug_printf("InitializeSecurityDescriptor %E"); debug_printf("InitializeSecurityDescriptor %E");
/* /*

View File

@ -19,7 +19,6 @@ details. */
#include <wingdi.h> #include <wingdi.h>
#include <winuser.h> #include <winuser.h>
#include <ctype.h> #include <ctype.h>
#include <paths.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h" #include "path.h"
@ -28,10 +27,9 @@ details. */
#include "sigproc.h" #include "sigproc.h"
#include "child_info.h" #include "child_info.h"
#include "pinfo.h" #include "pinfo.h"
#include "cygheap.h"
#include "perthread.h" #include "perthread.h"
extern BOOL allow_ntsec;
#define LINE_BUF_CHUNK (MAX_PATH * 2) #define LINE_BUF_CHUNK (MAX_PATH * 2)
suffix_info std_suffixes[] = suffix_info std_suffixes[] =
@ -171,7 +169,6 @@ handle (int n, int direction)
*/ */
HANDLE NO_COPY hExeced = NULL; HANDLE NO_COPY hExeced = NULL;
DWORD NO_COPY exec_exit = 0;
int int
iscmd (const char *argv0, const char *what) iscmd (const char *argv0, const char *what)
@ -242,19 +239,66 @@ exec_fixup_after_fork ()
hexec_proc = NULL; 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 static int __stdcall
spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv, spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
const char *const envp[], int mode) const char *const envp[], int mode)
{ {
int i; int i;
BOOL rc; BOOL rc;
int argc;
pid_t cygpid; pid_t cygpid;
hExeced = NULL; hExeced = NULL;
MALLOC_CHECK; MALLOC_CHECK;
// if (strstr (prog_arg, "dopath")) try_to_debug ();
if (prog_arg == NULL) if (prog_arg == NULL)
{ {
syscall_printf ("prog_arg is 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); return (-1);
} }
/* CreateProcess takes one long string that is the command line (sigh). path_conv real_path;
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;
linebuf one_line; 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"))) (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
{ {
one_line.add (argv[0]); one_line.add (argv[0]);
one_line.add (" "); one_line.add (" ");
one_line.add (argv[1]); one_line.add (argv[1]);
one_line.add (" "); one_line.add (" ");
real_path = NULL;
one_line.add (argv[2]); one_line.add (argv[2]);
strcpy (real_path_buf, argv[0]); strcpy (real_path, argv[0]);
goto skip_arg_parsing; goto skip_arg_parsing;
} }
real_path = real_path_buf;
const char *saved_prog_arg;
const char *newargv0, **firstarg;
const char *ext; const char *ext;
if ((ext = perhaps_suffix (prog_arg, real_path)) == NULL)
if ((ext = perhaps_suffix (prog_arg, real_path_buf)) == NULL)
{ {
set_errno (ENOENT); set_errno (ENOENT);
return -1; return -1;
} }
MALLOC_CHECK; 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 /* If the file name ends in either .exe, .com, .bat, or .cmd we assume
that it is NOT a script file */ 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] != '!') if (buf[0] != '#' || buf[1] != '!')
{ {
strcpy (buf, "sh"); /* shell script without magic */ pgm = (char *) "/bin/sh";
pgm = buf;
ptr = buf + 2; ptr = buf + 2;
arg1 = NULL; arg1 = NULL;
} }
@ -379,87 +445,84 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
ptr = newptr - 1; ptr = newptr - 1;
} }
*ptr = '\0'; *ptr = '\0';
} }
char buf2[MAX_PATH + 1];
/* pointers: /* pointers:
* pgm interpreter name * pgm interpreter name
* arg1 optional string * arg1 optional string
* ptr end of string * ptr end of string
*/ */
if (arg1)
newargv.unshift (arg1);
if (!arg1) find_exec (pgm, real_path, "PATH=", 0, &ext);
one_line.prepend (" ", 1); newargv.unshift (real_path, 1);
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++) if (real_path.iscygexec ())
{ for (int i = newargv.calloced; i < newargv.argc; i++)
char *p = NULL; newargv[i] = cstrdup (newargv[i]);
const char *a = newargv0 ?: *argv;
MALLOC_CHECK;
newargv0 = NULL;
int len = strlen (a);
if (len != 0 && !strpbrk (a, " \t\n\r\""))
one_line.add (a, len);
else
{
one_line.add ("\"", 1);
for (; (p = strpbrk (a, "\"\\")); a = ++p)
{
one_line.add (a, p - a);
if (*p == '\\' || *p == '"')
one_line.add ("\\", 1);
one_line.add (p, 1);
}
if (*a)
one_line.add (a);
one_line.add ("\"", 1);
}
MALLOC_CHECK;
one_line.add (" ", 1);
MALLOC_CHECK;
}
MALLOC_CHECK;
if (one_line.ix)
one_line.buf[one_line.ix - 1] = '\0';
else else
one_line.add ("", 1); {
MALLOC_CHECK; for (int i = 0; i < newargv.argc; i++)
{
char *p = NULL;
const char *a;
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);
else
{
one_line.add ("\"", 1);
for (; (p = strpbrk (a, "\"\\")); a = ++p)
{
one_line.add (a, p - a);
if (*p == '\\' || *p == '"')
one_line.add ("\\", 1);
one_line.add (p, 1);
}
if (*a)
one_line.add (a);
one_line.add ("\"", 1);
}
MALLOC_CHECK;
one_line.add (" ", 1);
MALLOC_CHECK;
}
MALLOC_CHECK;
if (one_line.ix)
one_line.buf[one_line.ix - 1] = '\0';
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: skip_arg_parsing:
PROCESS_INFORMATION pi = {NULL, 0, 0, 0}; 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.lpReserved = NULL;
si.lpDesktop = NULL; si.lpDesktop = NULL;
si.dwFlags = STARTF_USESTDHANDLES; si.dwFlags = STARTF_USESTDHANDLES;
@ -470,53 +533,7 @@ skip_arg_parsing:
/* Pass fd table to a child */ /* Pass fd table to a child */
MALLOC_CHECK; syscall_printf ("spawn_guts (%s, %.132s)", (char *) real_path, one_line.buf);
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);
int flags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED | int flags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED |
GetPriorityClass (hMainProc); GetPriorityClass (hMainProc);
@ -525,7 +542,14 @@ skip_arg_parsing:
flags |= DETACHED_PROCESS; flags |= DETACHED_PROCESS;
/* Build windows style environment list */ /* 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 */ /* Preallocated buffer for `sec_user' call */
char sa_buf[1024]; char sa_buf[1024];
@ -533,9 +557,12 @@ skip_arg_parsing:
if (!hToken && myself->token != INVALID_HANDLE_VALUE) if (!hToken && myself->token != INVALID_HANDLE_VALUE)
hToken = myself->token; 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 && if (mode == _P_OVERLAY && !hexec_proc &&
!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0, !DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
TRUE, DUPLICATE_SAME_ACCESS)) TRUE, DUPLICATE_SAME_ACCESS))
system_printf ("couldn't save current process handle %p, %E", hMainProc); system_printf ("couldn't save current process handle %p, %E", hMainProc);
if (hToken) if (hToken)
@ -561,22 +588,22 @@ skip_arg_parsing:
PSID sid = NULL; PSID sid = NULL;
DWORD ret_len; DWORD ret_len;
if (GetTokenInformation (hToken, TokenUser, if (GetTokenInformation (hToken, TokenUser,
(LPVOID) &tu, sizeof tu, (LPVOID) &tu, sizeof tu,
&ret_len)) &ret_len))
sid = ((TOKEN_USER *) &tu)->User.Sid; sid = ((TOKEN_USER *) &tu)->User.Sid;
else else
system_printf ("GetTokenInformation: %E"); system_printf ("GetTokenInformation: %E");
/* Retrieve security attributes before setting psid to NULL /* Retrieve security attributes before setting psid to NULL
since it's value is needed by `sec_user'. */ since it's value is needed by `sec_user'. */
PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid
? sec_user (sa_buf, sid) ? sec_user (sa_buf, sid)
: &sec_all_nih; : &sec_all_nih;
/* Remove impersonation */ /* Remove impersonation */
uid_t uid = geteuid(); uid_t uid = geteuid();
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (myself->orig_uid); seteuid (myself->orig_uid);
/* Load users registry hive. */ /* Load users registry hive. */
load_registry_hive (sid); load_registry_hive (sid);
@ -584,8 +611,8 @@ skip_arg_parsing:
rc = CreateProcessAsUser (hToken, rc = CreateProcessAsUser (hToken,
real_path, /* image name - with full path */ real_path, /* image name - with full path */
one_line.buf, /* what was passed to exec */ one_line.buf, /* what was passed to exec */
sec_attribs, /* process security attrs */ sec_attribs, /* process security attrs */
sec_attribs, /* thread security attrs */ sec_attribs, /* thread security attrs */
TRUE, /* inherit handles from parent */ TRUE, /* inherit handles from parent */
flags, flags,
envblock,/* environment */ envblock,/* environment */
@ -593,18 +620,18 @@ skip_arg_parsing:
&si, &si,
&pi); &pi);
/* Restore impersonation. In case of _P_OVERLAY this isn't /* Restore impersonation. In case of _P_OVERLAY this isn't
allowed since it would overwrite child data. */ 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) && myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (uid); seteuid (uid);
} }
else else
rc = CreateProcessA (real_path, /* image name - with full path */ rc = CreateProcessA (real_path, /* image name - with full path */
one_line.buf, /* what was passed to exec */ one_line.buf, /* what was passed to exec */
/* process security attrs */ /* process security attrs */
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih, allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
/* thread security attrs */ /* thread security attrs */
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih, allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
TRUE, /* inherit handles from parent */ TRUE, /* inherit handles from parent */
flags, flags,
envblock,/* environment */ envblock,/* environment */
@ -613,17 +640,13 @@ skip_arg_parsing:
&pi); &pi);
MALLOC_CHECK; MALLOC_CHECK;
free (envblock); if (envblock)
free (envblock);
MALLOC_CHECK; MALLOC_CHECK;
if (ciresrv->myself_pinfo)
CloseHandle (ciresrv->myself_pinfo);
/* Set errno now so that debugging messages from it appear before our /* Set errno now so that debugging messages from it appear before our
final debugging message [this is a general rule for debugging final debugging message [this is a general rule for debugging
messages]. */ messages]. */
if (!rc)
if (!rc) if (!rc)
{ {
if (spr) if (spr)
@ -651,8 +674,8 @@ skip_arg_parsing:
if (mode == _P_OVERLAY) if (mode == _P_OVERLAY)
{ {
close_all_files (); strcpy (myself->progname, real_path);
strcpy (myself->progname, real_path_buf); // close_all_files ();
proc_terminate (); proc_terminate ();
hExeced = pi.hProcess; hExeced = pi.hProcess;
@ -676,8 +699,6 @@ skip_arg_parsing:
} }
child->username[0] = '\0'; child->username[0] = '\0';
child->progname[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->ppid = myself->pid;
child->uid = myself->uid; child->uid = myself->uid;
child->gid = myself->gid; child->gid = myself->gid;
@ -723,7 +744,7 @@ skip_arg_parsing:
DWORD res; DWORD res;
if (mode == _P_OVERLAY) if (mode == _P_OVERLAY || mode == _P_VFORK)
{ {
BOOL exited; BOOL exited;
@ -732,54 +753,45 @@ skip_arg_parsing:
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST); SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
res = 0; res = 0;
DWORD timeout = INFINITE;
exec_exit = 1;
exited = FALSE; exited = FALSE;
MALLOC_CHECK; MALLOC_CHECK;
for (int i = 0; i < 100; i++) 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: case WAIT_OBJECT_0:
sigproc_printf ("subprocess exited"); sigproc_printf ("subprocess exited");
if (!GetExitCodeProcess (pi.hProcess, &res)) if (!GetExitCodeProcess (pi.hProcess, &res))
res = exec_exit; res = 1;
exited = TRUE; exited = TRUE;
}
if (nwait > 2) if (nwait <= 2 || mode != _P_OVERLAY)
if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0) /* nothing to do */;
res |= EXIT_REPARENTING; else if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0)
else if (!(res & EXIT_REPARENTING)) goto reparent;
{ else if (!(res & EXIT_REPARENTING))
MALLOC_CHECK; {
close_all_files (); MALLOC_CHECK;
MALLOC_CHECK; close_all_files ();
} MALLOC_CHECK;
}
break; break;
case WAIT_OBJECT_0 + 1: case WAIT_OBJECT_0 + 1:
sigproc_printf ("signal arrived"); sigproc_printf ("signal arrived");
ResetEvent (signal_arrived); ResetEvent (signal_arrived);
continue; continue;
case WAIT_OBJECT_0 + 2: case WAIT_OBJECT_0 + 2:
res = EXIT_REPARENTING; if (mode == _P_OVERLAY)
MALLOC_CHECK;
ForceCloseHandle (spr);
MALLOC_CHECK;
if (!parent_alive)
{ {
nwait = 1; reparent:
sigproc_terminate (); res |= EXIT_REPARENTING;
continue; close_all_files ();
if (!parent_alive)
{
nwait = 1;
sigproc_terminate ();
continue;
}
} }
break; break;
case WAIT_FAILED: case WAIT_FAILED:
@ -796,8 +808,7 @@ skip_arg_parsing:
break; break;
} }
if (nwait > 2) ForceCloseHandle (spr);
ForceCloseHandle (spr);
sigproc_printf ("res = %x", res); sigproc_printf ("res = %x", res);
@ -813,18 +824,19 @@ skip_arg_parsing:
/* nothing */; /* nothing */;
else else
{ {
int rc;
HANDLE hP = OpenProcess (PROCESS_ALL_ACCESS, FALSE, HANDLE hP = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
parent->dwProcessId); parent->dwProcessId);
sigproc_printf ("parent handle %p, pid %d", hP, parent->dwProcessId); sigproc_printf ("parent handle %p, pid %d", hP, parent->dwProcessId);
if (hP == NULL && GetLastError () == ERROR_INVALID_PARAMETER) if (hP == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
res = 1; rc = 1;
else if (hP) else if (hP)
{ {
ProtectHandle (hP); ProtectHandle (hP);
res = DuplicateHandle (hMainProc, pi.hProcess, hP, rc = DuplicateHandle (hMainProc, pi.hProcess, hP,
&myself->hProcess, 0, FALSE, &myself->hProcess, 0, FALSE,
DUPLICATE_SAME_ACCESS); DUPLICATE_SAME_ACCESS);
sigproc_printf ("Dup hP %d", res); sigproc_printf ("Dup hP %d", rc);
ForceCloseHandle (hP); ForceCloseHandle (hP);
} }
if (!res) if (!res)
@ -837,7 +849,6 @@ skip_arg_parsing:
system_printf ("myself->hProcess %x", myself->hProcess); system_printf ("myself->hProcess %x", myself->hProcess);
} }
} }
res = EXIT_REPARENTING;
ForceCloseHandle1 (hExeced, childhProc); ForceCloseHandle1 (hExeced, childhProc);
hExeced = INVALID_HANDLE_VALUE; hExeced = INVALID_HANDLE_VALUE;
} }
@ -848,15 +859,26 @@ skip_arg_parsing:
} }
MALLOC_CHECK; MALLOC_CHECK;
do_exit (res | EXIT_NOCLOSEALL); if (mode == _P_OVERLAY)
do_exit (res | EXIT_NOCLOSEALL);
} }
if (mode == _P_WAIT) switch (mode)
waitpid (cygpid, (int *) &res, 0); {
else if (mode == _P_DETACH) case _P_WAIT:
res = 0; /* Lose all memory of this child. */ waitpid (cygpid, (int *) &res, 0);
else if ((mode == _P_NOWAIT) || (mode == _P_NOWAITO)) break;
res = cygpid; case _P_DETACH:
res = 0; /* Lose all memory of this child. */
break;
case _P_NOWAIT:
case _P_NOWAITO:
case _P_VFORK:
res = cygpid;
break;
default:
break;
}
return (int) res; return (int) res;
} }
@ -889,29 +911,30 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
switch (mode) switch (mode)
{ {
case _P_OVERLAY: case _P_OVERLAY:
/* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/ /* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
/* Just act as an exec if _P_OVERLAY set. */ /* Just act as an exec if _P_OVERLAY set. */
spawn_guts (hToken, path, argv, envp, mode); spawn_guts (hToken, path, argv, envp, mode);
/* Errno should be set by spawn_guts. */ /* Errno should be set by spawn_guts. */
ret = -1; ret = -1;
break; break;
case _P_NOWAIT: case _P_VFORK:
case _P_NOWAITO: case _P_NOWAIT:
case _P_WAIT: case _P_NOWAITO:
case _P_DETACH: case _P_WAIT:
subproc_init (); case _P_DETACH:
ret = spawn_guts (hToken, path, argv, envp, mode); subproc_init ();
if (vf && ret > 0) ret = spawn_guts (hToken, path, argv, envp, 0);
{ if (vf && ret > 0)
vf->pid = ret; {
longjmp (vf->j, 1); vf->pid = ret;
} longjmp (vf->j, 1);
break; }
default: break;
set_errno (EINVAL); default:
ret = -1; set_errno (EINVAL);
break; ret = -1;
break;
} }
return ret; return ret;
} }

View File

@ -21,7 +21,6 @@ details. */
#include <sys/uio.h> #include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <unistd.h>
#include <winnls.h> #include <winnls.h>
#include <lmcons.h> /* for UNLEN */ #include <lmcons.h> /* for UNLEN */
#include "cygerrno.h" #include "cygerrno.h"
@ -32,6 +31,7 @@ details. */
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.h" #include "pinfo.h"
#include <unistd.h>
extern BOOL allow_ntsec; 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); debug_printf ("%s (%s, %p)", caller, name, buf);
path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL, path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) |
stat_suffixes); PC_FULL, stat_suffixes);
if (real_path.error) 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 * extern "C" char *
ctermid (char *str) ctermid (char *str)
{ {
@ -1434,20 +1444,8 @@ ctermid (char *str)
return 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 */ /* Tells stdio if it should do the cr/lf conversion for this file */
extern "C" int _cygwin_istext_for_stdio (int fd); extern "C" int
int
_cygwin_istext_for_stdio (int fd) _cygwin_istext_for_stdio (int fd)
{ {
syscall_printf("_cygwin_istext_for_stdio (%d)\n", 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 */ /* ftruncate: P96 5.6.7.1 */
extern "C" extern "C" int
int
ftruncate (int fd, off_t length) ftruncate (int fd, off_t length)
{ {
int res = -1; 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 */ /* truncate: Provided by SVR4 and 4.3+BSD. Not part of POSIX.1 or XPG3 */
/* FIXME: untested */ /* FIXME: untested */
extern "C" extern "C" int
int
truncate (const char *pathname, off_t length) truncate (const char *pathname, off_t length)
{ {
int fd; int fd;
@ -1632,8 +1628,7 @@ truncate (const char *pathname, off_t length)
return res; return res;
} }
extern "C" extern "C" long
long
get_osfhandle (int fd) get_osfhandle (int fd)
{ {
long res = -1; long res = -1;
@ -1651,8 +1646,7 @@ get_osfhandle (int fd)
return res; return res;
} }
extern "C" extern "C" int
int
statfs (const char *fname, struct statfs *sfs) statfs (const char *fname, struct statfs *sfs)
{ {
if (!sfs) if (!sfs)
@ -1692,8 +1686,7 @@ statfs (const char *fname, struct statfs *sfs)
return 0; return 0;
} }
extern "C" extern "C" int
int
fstatfs (int fd, struct statfs *sfs) fstatfs (int fd, struct statfs *sfs)
{ {
if (fdtab.not_open (fd)) if (fdtab.not_open (fd))
@ -1706,8 +1699,7 @@ fstatfs (int fd, struct statfs *sfs)
} }
/* setpgid: POSIX 4.3.3.1 */ /* setpgid: POSIX 4.3.3.1 */
extern "C" extern "C" int
int
setpgid (pid_t pid, pid_t pgid) setpgid (pid_t pid, pid_t pgid)
{ {
int res = -1; int res = -1;
@ -1746,8 +1738,7 @@ out:
return res; return res;
} }
extern "C" extern "C" pid_t
pid_t
getpgid (pid_t pid) getpgid (pid_t pid)
{ {
if (pid == 0) if (pid == 0)
@ -1762,22 +1753,19 @@ getpgid (pid_t pid)
return p->pgid; return p->pgid;
} }
extern "C" extern "C" int
int
setpgrp (void) setpgrp (void)
{ {
return setpgid (0, 0); return setpgid (0, 0);
} }
extern "C" extern "C" pid_t
pid_t
getpgrp (void) getpgrp (void)
{ {
return getpgid (0); return getpgid (0);
} }
extern "C" extern "C" char *
char *
ptsname (int fd) ptsname (int fd)
{ {
if (fdtab.not_open (fd)) if (fdtab.not_open (fd))
@ -1789,8 +1777,7 @@ ptsname (int fd)
} }
/* FIXME: what is this? */ /* FIXME: what is this? */
extern "C" extern "C" int
int
regfree () regfree ()
{ {
return 0; return 0;
@ -1802,8 +1789,7 @@ regfree ()
Although mknod hasn't been implemented yet, some GNU tools (e.g. the 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 fileutils) assume its existence so we must provide a stub that always
fails. */ fails. */
extern "C" extern "C" int
int
mknod () mknod ()
{ {
set_errno (ENOSYS); set_errno (ENOSYS);
@ -1811,8 +1797,7 @@ mknod ()
} }
/* setgid: POSIX 4.2.2.1 */ /* setgid: POSIX 4.2.2.1 */
extern "C" extern "C" int
int
setgid (gid_t gid) setgid (gid_t gid)
{ {
int ret = setegid (gid); int ret = setegid (gid);
@ -1822,8 +1807,7 @@ setgid (gid_t gid)
} }
/* setuid: POSIX 4.2.2.1 */ /* setuid: POSIX 4.2.2.1 */
extern "C" extern "C" int
int
setuid (uid_t uid) setuid (uid_t uid)
{ {
int ret = seteuid (uid); int ret = seteuid (uid);
@ -1836,8 +1820,7 @@ setuid (uid_t uid)
extern char *internal_getlogin (_pinfo *pi); extern char *internal_getlogin (_pinfo *pi);
/* seteuid: standards? */ /* seteuid: standards? */
extern "C" extern "C" int
int
seteuid (uid_t uid) seteuid (uid_t uid)
{ {
if (os_being_run == winNT) if (os_being_run == winNT)

View File

@ -196,7 +196,7 @@ MTinterface::Find (void *_value, int (*comp) (void *, void *), register int &_in
{ {
current = _list->items[_index]; current = _list->items[_index];
if (current->used && comp (current, _value)) if (current->used && comp (current, _value))
break; break;
current = NULL; current = NULL;
} }
return current; return current;
@ -211,7 +211,7 @@ MTinterface::Find (MTitem & _item, MTList * _list)
{ {
current = _list->items[_index]; current = _list->items[_index];
if (current->used && current == &_item) if (current->used && current == &_item)
break; break;
} }
return (_index == _list->index ? -1 : _index); return (_index == _list->index ? -1 : _index);
}; };
@ -481,7 +481,7 @@ thread_init_wrapper (void *_arg)
struct _reent local_clib; struct _reent local_clib;
struct sigaction _sigs[NSIG]; struct sigaction _sigs[NSIG];
sigset_t _sig_mask; /* one set for everything to ignore. */ sigset_t _sig_mask; /* one set for everything to ignore. */
LONG _sigtodo[NSIG + __SIGOFFSET]; LONG _sigtodo[NSIG + __SIGOFFSET];
// setup signal structures // setup signal structures
@ -520,7 +520,7 @@ thread_init_wrapper (void *_arg)
// FIX ME : cleanup code // FIX ME : cleanup code
// thread->used = false; // release thread entry // thread->used = false; // release thread entry
thread->return_ptr = ret; thread->return_ptr = ret;
ExitThread (0); ExitThread (0);
} }
@ -595,7 +595,7 @@ __pthread_join (pthread_t * thread, void **return_val)
if (item->joinable == 'N') if (item->joinable == 'N')
{ {
if (return_val) if (return_val)
*return_val = NULL; *return_val = NULL;
return EINVAL; return EINVAL;
} }
else else
@ -603,7 +603,7 @@ __pthread_join (pthread_t * thread, void **return_val)
item->joinable = 'N'; item->joinable = 'N';
WaitForSingleObject ((HANDLE)*thread, INFINITE); WaitForSingleObject ((HANDLE)*thread, INFINITE);
if (return_val) if (return_val)
*return_val = item->return_ptr; *return_val = item->return_ptr;
}/* End if*/ }/* End if*/
return 0; return 0;
@ -651,7 +651,7 @@ __pthread_continue (pthread_t * thread)
return ESRCH; return ESRCH;
if (item->suspended == true) if (item->suspended == true)
ResumeThread ((HANDLE)*thread); ResumeThread ((HANDLE)*thread);
item->suspended = false; item->suspended = false;
return 0; return 0;
@ -994,4 +994,4 @@ extern "C"
} }
} }
#endif // MT_SAFE #endif // MT_SAFE

View File

@ -74,9 +74,6 @@ struct _winsup_t
/* path.cc */ /* path.cc */
struct mntent _ret; struct mntent _ret;
char *_cwd_win32;
char *_cwd_posix;
unsigned long _cwd_hash;
int _iteration; int _iteration;
/* strerror */ /* strerror */
@ -306,6 +303,6 @@ int __sem_post (sem_t * sem);
}; };
#endif // MT_SAFE #endif // MT_SAFE
#endif // _CYGNUS_THREADS_ #endif // _CYGNUS_THREADS_

View File

@ -40,130 +40,130 @@ internal_getlogin (_pinfo *pi)
/* First trying to get logon info from environment */ /* First trying to get logon info from environment */
if ((env = getenv ("USERNAME")) != NULL) if ((env = getenv ("USERNAME")) != NULL)
un = env; un = env;
if ((env = getenv ("LOGONSERVER")) != NULL) if ((env = getenv ("LOGONSERVER")) != NULL)
strcpy (pi->logsrv, env + 2); /* filter leading double backslashes */ strcpy (pi->logsrv, env + 2); /* filter leading double backslashes */
if ((env = getenv ("USERDOMAIN")) != NULL) if ((env = getenv ("USERDOMAIN")) != NULL)
strcpy (pi->domain, env); strcpy (pi->domain, env);
/* Trust only if usernames are identical */ /* Trust only if usernames are identical */
if (un && strcasematch (pi->username, un) if (un && strcasematch (pi->username, un)
&& pi->domain[0] && pi->logsrv[0]) && pi->domain[0] && pi->logsrv[0])
debug_printf ("Domain: %s, Logon Server: %s", pi->domain, pi->logsrv); debug_printf ("Domain: %s, Logon Server: %s", pi->domain, pi->logsrv);
/* If that failed, try to get that info from NetBIOS */ /* If that failed, try to get that info from NetBIOS */
else if (!NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&wui)) else if (!NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&wui))
{ {
sys_wcstombs (pi->username, wui->wkui1_username, MAX_USER_NAME); sys_wcstombs (pi->username, wui->wkui1_username, MAX_USER_NAME);
sys_wcstombs (pi->logsrv, wui->wkui1_logon_server, MAX_HOST_NAME); sys_wcstombs (pi->logsrv, wui->wkui1_logon_server, MAX_HOST_NAME);
sys_wcstombs (pi->domain, wui->wkui1_logon_domain, sys_wcstombs (pi->domain, wui->wkui1_logon_domain,
MAX_COMPUTERNAME_LENGTH + 1); MAX_COMPUTERNAME_LENGTH + 1);
/* Save values in environment */ /* Save values in environment */
if (!strcasematch (pi->username, "SYSTEM") if (!strcasematch (pi->username, "SYSTEM")
&& pi->domain[0] && pi->logsrv[0]) && pi->domain[0] && pi->logsrv[0])
{ {
LPUSER_INFO_3 ui = NULL; LPUSER_INFO_3 ui = NULL;
WCHAR wbuf[MAX_HOST_NAME + 2]; WCHAR wbuf[MAX_HOST_NAME + 2];
strcat (strcpy (buf, "\\\\"), pi->logsrv); strcat (strcpy (buf, "\\\\"), pi->logsrv);
setenv ("USERNAME", pi->username, 1); setenv ("USERNAME", pi->username, 1);
setenv ("LOGONSERVER", buf, 1); setenv ("LOGONSERVER", buf, 1);
setenv ("USERDOMAIN", pi->domain, 1); setenv ("USERDOMAIN", pi->domain, 1);
/* HOMEDRIVE and HOMEPATH are wrong most of the time, too, /* HOMEDRIVE and HOMEPATH are wrong most of the time, too,
after changing user context! */ after changing user context! */
sys_mbstowcs (wbuf, buf, MAX_HOST_NAME + 2); sys_mbstowcs (wbuf, buf, MAX_HOST_NAME + 2);
if (!NetUserGetInfo (NULL, wui->wkui1_username, 3, (LPBYTE *)&ui) if (!NetUserGetInfo (NULL, wui->wkui1_username, 3, (LPBYTE *)&ui)
|| !NetUserGetInfo (wbuf,wui->wkui1_username,3,(LPBYTE *)&ui)) || !NetUserGetInfo (wbuf,wui->wkui1_username,3,(LPBYTE *)&ui))
{ {
sys_wcstombs (buf, ui->usri3_home_dir, MAX_PATH); sys_wcstombs (buf, ui->usri3_home_dir, MAX_PATH);
if (!buf[0]) if (!buf[0])
{ {
sys_wcstombs (buf, ui->usri3_home_dir_drive, MAX_PATH); sys_wcstombs (buf, ui->usri3_home_dir_drive, MAX_PATH);
if (buf[0]) if (buf[0])
strcat (buf, "\\"); strcat (buf, "\\");
else else
{ {
env = getenv ("SYSTEMDRIVE"); env = getenv ("SYSTEMDRIVE");
if (env && *env) if (env && *env)
strcat (strcpy (buf, env), "\\"); strcat (strcpy (buf, env), "\\");
else else
GetSystemDirectoryA (buf, MAX_PATH); GetSystemDirectoryA (buf, MAX_PATH);
} }
} }
setenv ("HOMEPATH", buf + 2, 1); setenv ("HOMEPATH", buf + 2, 1);
buf[2] = '\0'; buf[2] = '\0';
setenv ("HOMEDRIVE", buf, 1); setenv ("HOMEDRIVE", buf, 1);
NetApiBufferFree (ui); NetApiBufferFree (ui);
} }
} }
debug_printf ("Domain: %s, Logon Server: %s, Windows Username: %s", debug_printf ("Domain: %s, Logon Server: %s, Windows Username: %s",
pi->domain, pi->logsrv, pi->username); pi->domain, pi->logsrv, pi->username);
NetApiBufferFree (wui); NetApiBufferFree (wui);
} }
if (allow_ntsec) if (allow_ntsec)
{ {
HANDLE ptok = pi->token; /* Which is INVALID_HANDLE_VALUE if no HANDLE ptok = pi->token; /* Which is INVALID_HANDLE_VALUE if no
impersonation took place. */ impersonation took place. */
DWORD siz; DWORD siz;
char tu[1024]; char tu[1024];
int ret = 0; int ret = 0;
/* Try to get the SID either from already impersonated token /* Try to get the SID either from already impersonated token
or from current process first. To differ that two cases is or from current process first. To differ that two cases is
important, because you can't rely on the user information important, because you can't rely on the user information
in a process token of a currently impersonated process. */ in a process token of a currently impersonated process. */
if (ptok == INVALID_HANDLE_VALUE if (ptok == INVALID_HANDLE_VALUE
&& !OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &ptok)) && !OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &ptok))
debug_printf ("OpenProcessToken(): %E\n"); debug_printf ("OpenProcessToken(): %E\n");
else if (!GetTokenInformation (ptok, TokenUser, (LPVOID) &tu, else if (!GetTokenInformation (ptok, TokenUser, (LPVOID) &tu,
sizeof tu, &siz)) sizeof tu, &siz))
debug_printf ("GetTokenInformation(): %E"); debug_printf ("GetTokenInformation(): %E");
else if (!(ret = CopySid (MAX_SID_LEN, (PSID) pi->psid, else if (!(ret = CopySid (MAX_SID_LEN, (PSID) pi->psid,
((TOKEN_USER *) &tu)->User.Sid))) ((TOKEN_USER *) &tu)->User.Sid)))
debug_printf ("Couldn't retrieve SID from access token!"); debug_printf ("Couldn't retrieve SID from access token!");
/* Close token only if it's a result from OpenProcessToken(). */ /* Close token only if it's a result from OpenProcessToken(). */
if (ptok != INVALID_HANDLE_VALUE && pi->token == INVALID_HANDLE_VALUE) if (ptok != INVALID_HANDLE_VALUE && pi->token == INVALID_HANDLE_VALUE)
CloseHandle (ptok); CloseHandle (ptok);
/* If that failes, try to get the SID from localhost. This can only /* If that failes, try to get the SID from localhost. This can only
be done if a domain is given because there's a chance that a local be done if a domain is given because there's a chance that a local
and a domain user may have the same name. */ and a domain user may have the same name. */
if (!ret && pi->domain[0]) if (!ret && pi->domain[0])
{ {
/* Concat DOMAIN\USERNAME for the next lookup */ /* Concat DOMAIN\USERNAME for the next lookup */
strcat (strcat (strcpy (buf, pi->domain), "\\"), pi->username); strcat (strcat (strcpy (buf, pi->domain), "\\"), pi->username);
if (!(ret = lookup_name (buf, NULL, (PSID) pi->psid))) if (!(ret = lookup_name (buf, NULL, (PSID) pi->psid)))
debug_printf ("Couldn't retrieve SID locally!"); debug_printf ("Couldn't retrieve SID locally!");
} }
/* If that failes, too, as a last resort try to get the SID from /* If that failes, too, as a last resort try to get the SID from
the logon server. */ the logon server. */
if (!ret && !(ret = lookup_name(pi->username, pi->logsrv, if (!ret && !(ret = lookup_name(pi->username, pi->logsrv,
(PSID)pi->psid))) (PSID)pi->psid)))
debug_printf ("Couldn't retrieve SID from '%s'!", pi->logsrv); debug_printf ("Couldn't retrieve SID from '%s'!", pi->logsrv);
/* If we have a SID, try to get the corresponding Cygwin user name /* If we have a SID, try to get the corresponding Cygwin user name
which can be different from the Windows user name. */ which can be different from the Windows user name. */
if (ret) if (ret)
{ {
struct passwd *pw; struct passwd *pw;
char psidbuf[MAX_SID_LEN]; char psidbuf[MAX_SID_LEN];
PSID psid = (PSID) psidbuf; PSID psid = (PSID) psidbuf;
pi->use_psid = 1; pi->use_psid = 1;
if (!strcasematch (pi->username, "SYSTEM") if (!strcasematch (pi->username, "SYSTEM")
&& pi->domain[0] && pi->logsrv[0]) && pi->domain[0] && pi->logsrv[0])
{ {
if (get_registry_hive_path (pi->psid, buf)) if (get_registry_hive_path (pi->psid, buf))
setenv ("USERPROFILE", buf, 1); setenv ("USERPROFILE", buf, 1);
} }
while ((pw = getpwent ()) != NULL) while ((pw = getpwent ()) != NULL)
if (get_pw_sid (psid, pw) && EqualSid (pi->psid, psid)) if (get_pw_sid (psid, pw) && EqualSid (pi->psid, psid))
{ {
strcpy (pi->username, pw->pw_name); strcpy (pi->username, pw->pw_name);
break; break;
} }
endpwent (); endpwent ();
} }
} }
} }
debug_printf ("Cygwins Username: %s", pi->username); debug_printf ("Cygwins Username: %s", pi->username);
return pi->username; return pi->username;
@ -187,13 +187,13 @@ uinfo_init ()
if (myself->uid == USHRT_MAX) if (myself->uid == USHRT_MAX)
if ((p = getpwnam (username = internal_getlogin (myself))) != NULL) if ((p = getpwnam (username = internal_getlogin (myself))) != NULL)
{ {
myself->uid = p->pw_uid; myself->uid = p->pw_uid;
myself->gid = p->pw_gid; myself->gid = p->pw_gid;
} }
else else
{ {
myself->uid = DEFAULT_UID; myself->uid = DEFAULT_UID;
myself->gid = DEFAULT_GID; myself->gid = DEFAULT_GID;
} }
/* Real and effective uid/gid are always identical on process start up. /* Real and effective uid/gid are always identical on process start up.
This is at least true for NT/W2K. */ This is at least true for NT/W2K. */

View File

@ -1,6 +1,6 @@
/* winsup.h: main Cygwin header file. /* 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. This file is part of Cygwin.
@ -83,9 +83,9 @@ extern os_type os_being_run;
extern int dynamically_loaded; extern int dynamically_loaded;
#define sys_wcstombs(tgt,src,len) \ #define sys_wcstombs(tgt,src,len) \
WideCharToMultiByte(CP_ACP,0,(src),-1,(tgt),(len),NULL,NULL) WideCharToMultiByte(CP_ACP,0,(src),-1,(tgt),(len),NULL,NULL)
#define sys_mbstowcs(tgt,src,len) \ #define sys_mbstowcs(tgt,src,len) \
MultiByteToWideChar(CP_ACP,0,(src),-1,(tgt),(len)) MultiByteToWideChar(CP_ACP,0,(src),-1,(tgt),(len))
#include <cygwin/version.h> #include <cygwin/version.h>
@ -200,11 +200,7 @@ extern "C" int dll_noncygwin_dllcrt0 (HMODULE, per_process *);
extern "C" void __stdcall do_exit (int) __attribute__ ((noreturn)); extern "C" void __stdcall do_exit (int) __attribute__ ((noreturn));
/* Initialize the environment */ /* Initialize the environment */
void environ_init (int); void environ_init (char **);
/* Heap management. */
void heap_init (void);
void malloc_init (void);
/* UID/GID */ /* UID/GID */
void uinfo_init (void); void uinfo_init (void);
@ -236,7 +232,7 @@ extern int cygwin_finished_initializing;
/* File manipulation */ /* File manipulation */
int __stdcall set_process_privileges (); int __stdcall set_process_privileges ();
int __stdcall get_file_attribute (int, const char *, int *, int __stdcall get_file_attribute (int, const char *, int *,
uid_t * = NULL, gid_t * = NULL); uid_t * = NULL, gid_t * = NULL);
int __stdcall set_file_attribute (int, const char *, int); int __stdcall set_file_attribute (int, const char *, int);
int __stdcall set_file_attribute (int, const char *, uid_t, gid_t, int, const char *); int __stdcall set_file_attribute (int, const char *, uid_t, gid_t, int, const char *);
void __stdcall set_std_handle (int); void __stdcall set_std_handle (int);
@ -258,6 +254,7 @@ extern "C" char *__stdcall rootdir (char *full_path);
void __stdcall mark (const char *, int); void __stdcall mark (const char *, int);
#define _P_VFORK 0
extern "C" int _spawnve (HANDLE hToken, int mode, const char *path, extern "C" int _spawnve (HANDLE hToken, int mode, const char *path,
const char *const *argv, const char *const *envp); 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); void __stdcall totimeval (struct timeval *dst, FILETIME * src, int sub, int flag);
long __stdcall to_time_t (FILETIME * ptr); 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 */ /* Retrieve a security descriptor that allows all access */
SECURITY_DESCRIPTOR *__stdcall get_null_sd (void); SECURITY_DESCRIPTOR *__stdcall get_null_sd (void);
@ -375,6 +366,7 @@ void __stdcall update_envptrs ();
char * __stdcall winenv (const char * const *, int); char * __stdcall winenv (const char * const *, int);
extern char **__cygwin_environ, ***main_environ; extern char **__cygwin_environ, ***main_environ;
extern "C" char __stdcall **cur_environ (); extern "C" char __stdcall **cur_environ ();
int __stdcall envsize (const char * const *, int debug_print = 0);
/* The title on program start. */ /* The title on program start. */
extern char *old_title; extern char *old_title;