4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-20 05:19:21 +08:00

* Makefile.in: Add cygheap.o.

* child_info.h: Add specific exec class.
* cygheap.h: New file.  Contains declarations for cygwin heap.
* cygheap.cc: New file.  Implements cygwin heap functions.
* dcrt0.cc (quoted): Simplify due to new method for passing arguments between
cygwin programs.
(alloc_stack_hard_way): Attempt to handle overlapped stack.
(dll_crt0_1): Move child_info processing here.  Accomodate new method for
passing arguments between cygwin programs.  Initialize cygwin heap.  Establish
__argc and __argv variables.
(_dll_crt0): Move most of child_info processing to dll_crt0_1.
(cygwin_dll_init): Remove duplication.
* dtable.cc (dtable::extend): Allocate dtable using cygwin heap.
(dtable::build_fhandler): Ditto for fhandler type being constructed.
(dtable::dup_worker): Free new fhandler from cygwin heap on error.
(dtable::select_*): Don't assume that this == fdtab.
(dtable::linearize_fd_array): Delete.
(dtable::delinearize_fd_array): Delete.
(dtable::fixup_after_exec): New file.
(dtable::vfork_child_dup): Use cygwin heap.
(dtable::vfork_parent_restore): Ditto.
* dtable.h: Remove obsolete methods.  Add new method.
* environ.cc (posify): Eliminate already_posix parameter and logic.
(envsize): New function.
(_addenv): Use envsize.
(environ_init): Accept an argument pointing to an existing environment list.
If supplied, allocate space for this in the the program's heap.
* fhandler.cc (fhandler_base::operator =): Move here from fhandler.h.  Use
cygwin heap to allocate filenames.
(fhandler_base::set_name): Allocate/free names from cygwin heap.
(fhandler_base::linearize): Delete.
(fhandler_base::de_linearize): Delete.
(fhandler_base::operator delete): Free from cygwin heap.
(fhandler_base::~fhandler_base): Ditto.
* fhandler.h: Accomodate elimination of *linearize and other changes above.
* fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from
de_linearize.
* heap.h: New file.
* fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for
name.  fhandler_tty::fixup_after_exec): Rename from de_linearize.
* fork.cc (fork): Call cygheap_fixup_in_child.
* heap.cc: Use declarations in heap.h.
* malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc
something from the cygwin heap.
* path.cc: Throughout, eliminate use of per-thread cache for cwd.  Use cwd_*
functions rather than cwd_* variables to access cwd_win32 and cwd_posix.
(cwd_win32): New function.
(cwd_posix): New function.
(cwd_hash): New function.
(cwd_fixup_after_exec): New function.
* path.h: Accomodate path.cc changes.
* pinfo.cc (pinfo_init): Accept a pointer to an environment table.  Pass this
to environ_init.  Eliminate old 'title' tests.
* pinfo.h: Accomodate above change in argument.
* spawn.cc (struct av): New method for building argv list.
(av::unshift): New method.
(spawn_guts): Allocate everything that the child process needs in the cygwin
heap and pass a pointer to this to the child.  Build argv list using new
method.  Eliminate delinearize stuff.
* thread.h: Eliminate _cwd_win32 and _cwd_posix buffers.
* winsup.h: Eliminate obsolete functions.  Add envsize() declaration.
This commit is contained in:
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

@ -45,7 +45,7 @@ __assert (const char *file, int line, const char *failedexpr)
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"
@ -293,17 +295,28 @@ 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)
{ {
char *p;
strcpy (cmd, cmd + 1);
if ((p = strchr (cmd, quote)) != NULL)
strcpy (p, p + 1);
return p + 1;
}
/* This must have been run from a Windows shell, so preserve
quotes for globify to play with later. */
while (*++cmd) while (*++cmd)
if ((p = strchr (cmd, quote)) == NULL) if ((p = strpbrk (cmd, "\\\"")) == NULL)
{ {
cmd = strchr (cmd, '\0'); // no closing quote cmd = strchr (cmd, '\0'); // no closing quote
break; break;
} }
else if (p[1] == quote && p[-1] != '\\') else if (quote == '\'')
continue;
else if (*p == '\\')
cmd = ++p;
else if (p[1] == quote)
{ {
*p = '\\'; *p = '\\';
cmd = ++p; // a quoted quote cmd = ++p; // a quoted quote
@ -316,37 +329,6 @@ quoted (char *cmd, int winshell)
return cmd; return cmd;
} }
/* When running as a child of a cygwin process, the quoted
characters should have been placed here by spawn_guts, so
we'll just pinch them out of the command string unless
they're quoted with a preceding \ */
p = cmd + 1;
while (*p)
{
if (*p == '\\' && p[1] == '\\')
{
strcpy (p, p + 1);
p++;
}
else if (*p != quote)
p++;
else if (p[-1] == '\\')
strcpy (p - 1, p);
else if (p[1] == quote)
{
strcpy (p, p + 1);
p++;
}
else
{
strcpy (p, p + 1);
break;
}
}
strcpy (cmd, cmd + 1);
return p - 1;
}
/* Perform a glob on word if it contains wildcard characters. /* Perform a glob on word if it contains wildcard characters.
Also quote every character between quotes to force glob to Also quote every character between quotes to force glob to
treat the characters literally. */ treat the characters literally. */
@ -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");
if (!noguard)
{
m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1); m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT, if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
PAGE_EXECUTE_READWRITE|PAGE_GUARD)) PAGE_EXECUTE_READWRITE|PAGE_GUARD))
api_fatal ("fork: couldn't allocate new stack guard page %p, %E", api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
m.BaseAddress); 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 ();
#endif regthread ("main", GetCurrentThreadId ());
char **envp = NULL;
if (child_proc_info)
{
switch (child_proc_info->type)
{
case PROC_FORK:
case PROC_FORK1:
alloc_stack (fork_info);
set_myself (mypid);
user_data->forkee = child_proc_info->cygpid;
user_data->heaptop = child_proc_info->heaptop;
user_data->heapbase = child_proc_info->heapbase;
user_data->heapptr = child_proc_info->heapptr;
ProtectHandle (child_proc_info->forker_finished);
break;
case PROC_EXEC:
case PROC_SPAWN:
HANDLE h;
cygheap = spawn_info->cygheap;
cygheap_max = spawn_info->cygheap_max;
cygheap_fixup_in_child (spawn_info->parent);
if (!spawn_info->moreinfo->myself_pinfo ||
!DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
hMainProc, &h, 0, 0,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
h = NULL;
set_myself (mypid, h);
__argc = spawn_info->moreinfo->argc;
__argv = spawn_info->moreinfo->argv;
envp = spawn_info->moreinfo->environ;
cwd_fixup_after_exec (spawn_info->moreinfo->cwd_win32,
spawn_info->moreinfo->cwd_posix,
spawn_info->moreinfo->cwd_hash);
fdtab.fixup_after_exec (spawn_info->parent, spawn_info->moreinfo->nfds,
spawn_info->moreinfo->fds);
CloseHandle (spawn_info->parent);
if (spawn_info->moreinfo->old_title)
{
old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
cfree (spawn_info->moreinfo->old_title);
}
ProtectHandle (child_proc_info->subproc_ready);
break;
}
}
ProtectHandle (hMainProc);
ProtectHandle (hMainThread);
/* Initialize the host dependent constants object. */ /* 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 /* Scan the command line and build argv. Expand wildcards if not
called from another cygwin process. */ called from another cygwin process. */
build_argv (line, argv, argc, build_argv (line, __argv, __argc,
NOTSTATE (myself, PID_CYGPARENT) && allow_glob); NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
/* Convert argv[0] to posix rules if it's currently blatantly /* Convert argv[0] to posix rules if it's currently blatantly
win32 style. */ win32 style. */
if ((strchr (argv[0], ':')) || (strchr (argv[0], '\\'))) if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
{ {
char *new_argv0 = (char *) alloca (MAX_PATH); char *new_argv0 = (char *) alloca (MAX_PATH);
cygwin_conv_to_posix_path (argv[0], new_argv0); cygwin_conv_to_posix_path (__argv[0], new_argv0);
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

@ -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,10 +113,6 @@ posify (int already_posix, char **here, const char *value)
if (!(conv = getwinenv (src))) if (!(conv = getwinenv (src)))
return; return;
if (already_posix)
conv->add_cache (value, NULL);
else
{
/* Turn all the items from c:<foo>;<bar> into their /* Turn all the items from c:<foo>;<bar> into their
mounted equivalents - if there is one. */ mounted equivalents - if there is one. */
@ -127,7 +125,6 @@ posify (int already_posix, char **here, const char *value)
*here = outenv; *here = outenv;
free (src); free (src);
} }
}
/* /*
* my_findenv -- * my_findenv --
@ -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. */
@ -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,6 +27,20 @@ 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)
{ {
@ -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);
} }
@ -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
@ -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

@ -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"
@ -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;
@ -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

@ -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

@ -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"
@ -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

@ -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

@ -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

@ -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

@ -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,55 +445,34 @@ 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);
}
if (real_path.iscygexec ())
for (int i = newargv.calloced; i < newargv.argc; i++)
newargv[i] = cstrdup (newargv[i]);
else else
{ {
one_line.prepend ("\" ", 2); for (int i = 0; i < newargv.argc; i++)
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++)
{ {
char *p = NULL; char *p = NULL;
const char *a = newargv0 ?: *argv; const char *a;
MALLOC_CHECK; if (i >= newargv.calloced)
newargv[i] = cstrdup (newargv[i]);
newargv0 = NULL; a = newargv[i];
int len = strlen (a); int len = strlen (a);
if (len != 0 && !strpbrk (a, " \t\n\r\"")) if (len != 0 && !strpbrk (a, " \t\n\r\""))
one_line.add (a, len); one_line.add (a, len);
@ -456,10 +501,28 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
else else
one_line.add ("", 1); one_line.add ("", 1);
MALLOC_CHECK; 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,6 +557,9 @@ 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))
@ -594,7 +621,7 @@ skip_arg_parsing:
&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);
} }
@ -613,17 +640,13 @@ skip_arg_parsing:
&pi); &pi);
MALLOC_CHECK; MALLOC_CHECK;
if (envblock)
free (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,33 +753,22 @@ 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)
goto reparent;
else if (!(res & EXIT_REPARENTING)) else if (!(res & EXIT_REPARENTING))
{ {
MALLOC_CHECK; MALLOC_CHECK;
@ -771,16 +781,18 @@ skip_arg_parsing:
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); reparent:
MALLOC_CHECK; res |= EXIT_REPARENTING;
close_all_files ();
if (!parent_alive) if (!parent_alive)
{ {
nwait = 1; nwait = 1;
sigproc_terminate (); sigproc_terminate ();
continue; continue;
} }
}
break; break;
case WAIT_FAILED: case WAIT_FAILED:
DWORD r; DWORD r;
@ -796,7 +808,6 @@ 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;
if (mode == _P_OVERLAY)
do_exit (res | EXIT_NOCLOSEALL); do_exit (res | EXIT_NOCLOSEALL);
} }
if (mode == _P_WAIT) switch (mode)
{
case _P_WAIT:
waitpid (cygpid, (int *) &res, 0); waitpid (cygpid, (int *) &res, 0);
else if (mode == _P_DETACH) break;
case _P_DETACH:
res = 0; /* Lose all memory of this child. */ res = 0; /* Lose all memory of this child. */
else if ((mode == _P_NOWAIT) || (mode == _P_NOWAITO)) break;
case _P_NOWAIT:
case _P_NOWAITO:
case _P_VFORK:
res = cygpid; res = cygpid;
break;
default:
break;
}
return (int) res; return (int) res;
} }
@ -896,12 +918,13 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
/* Errno should be set by spawn_guts. */ /* Errno should be set by spawn_guts. */
ret = -1; ret = -1;
break; break;
case _P_VFORK:
case _P_NOWAIT: case _P_NOWAIT:
case _P_NOWAITO: case _P_NOWAITO:
case _P_WAIT: case _P_WAIT:
case _P_DETACH: case _P_DETACH:
subproc_init (); subproc_init ();
ret = spawn_guts (hToken, path, argv, envp, mode); ret = spawn_guts (hToken, path, argv, envp, 0);
if (vf && ret > 0) if (vf && ret > 0)
{ {
vf->pid = ret; vf->pid = 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

@ -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 */

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.
@ -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);
@ -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;