/* dcrt0.cc -- essentially the main() for the Cygwin dll
- Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
This file is part of Cygwin.
#include "exceptions.h"
#include <ctype.h>
#include <limits.h>
+#include <wingdi.h>
+#include <winuser.h>
+#include <errno.h>
#include "sync.h"
#include "sigproc.h"
#include "pinfo.h"
-#include "cygheap.h"
#include "heap.h"
#include "cygerrno.h"
-#include "fhandler.h"
-#include "child_info.h"
#define NEED_VFORK
-#include "perthread.h"
+#include "perprocess.h"
+#include "security.h"
+#include "fhandler.h"
#include "path.h"
#include "dtable.h"
+#include "cygheap.h"
+#include "child_info.h"
+#include "perthread.h"
#include "shared_info.h"
#include "cygwin_version.h"
-#include "perprocess.h"
#include "dll_init.h"
-#include "host_dependent.h"
-#include "security.h"
#define MAX_AT_FILE_LEVEL 10
-#define PREMAIN_LEN (sizeof(user_data->premain) / sizeof (user_data->premain[0]))
+#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
HANDLE NO_COPY hMainProc = NULL;
HANDLE NO_COPY hMainThread = NULL;
&signal_dispatch_storage,
NULL};
-BOOL display_title = FALSE;
-BOOL strip_title_path = FALSE;
+BOOL display_title;
+BOOL strip_title_path;
BOOL allow_glob = TRUE;
+codepage_type current_codepage = ansi_cp;
-HANDLE NO_COPY parent_alive = NULL;
-int cygwin_finished_initializing = 0;
+int cygwin_finished_initializing;
/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
This is subtracted from the signal number prior to shifting the bit.
bit for masking. So, we'll temporarily detect this and set it to zero
for programs that are linked using older cygwins. This is just a stopgap
measure to allow an orderly transfer to the new, correct sigmask method. */
-unsigned int signal_shift_subtract = 1;
+unsigned NO_COPY int signal_shift_subtract = 1;
ResourceLocks _reslock NO_COPY;
-MTinterface _mtinterf NO_COPY;
+MTinterface _mtinterf;
+
+bool NO_COPY _cygwin_testing;
+unsigned NO_COPY _cygwin_testing_magic;
extern "C"
{
char **__cygwin_environ;
char ***main_environ;
/* __progname used in getopt error message */
- char *__progname = NULL;
- struct _reent reent_data;
+ char *__progname;
+ struct _reent reent_data = _REENT_INIT(reent_data);
struct per_process __cygwin_user_data =
{/* initial_sp */ 0, /* magic_biscuit */ 0,
/* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
/* calloc */ export_calloc,
/* premain */ {NULL, NULL, NULL, NULL},
/* run_ctors_p */ 0,
- /* unused */ { 0, 0, 0},
- /* heapbase */ NULL, /* heapptr */ NULL, /* heaptop */ NULL,
- /* unused1 */ 0, /* forkee */ 0, /* hmodule */ NULL,
+ /* unused */ {0, 0, 0, 0, 0, 0, 0},
+ /* forkee */ 0,
+ /* hmodule */ NULL,
/* api_major */ CYGWIN_VERSION_API_MAJOR,
/* api_minor */ CYGWIN_VERSION_API_MINOR,
/* unused2 */ {0, 0, 0, 0, 0},
/* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
/* impure_ptr */ &reent_data,
};
- BOOL ignore_case_with_glob = FALSE;
+ bool ignore_case_with_glob;
+ int __declspec (dllexport) _check_for_executable = TRUE;
+#ifdef DEBUGGING
+ int pinger;
+#endif
};
-char *old_title = NULL;
+char *old_title;
char title_buf[TITLESIZE + 1];
static void
atexit (do_global_dtors);
}
-/* remember the type of Win32 OS being run for future use. */
-os_type NO_COPY os_being_run;
-char NO_COPY osname[40];
-
-/* set_os_type: Set global variable os_being_run with type of Win32
- operating system being run. This information is used internally
- to manage the inconsistency in Win32 API calls between Win32 OSes. */
-/* Cygwin internal */
-static void
-set_os_type ()
-{
- OSVERSIONINFO os_version_info;
- const char *os;
-
- memset (&os_version_info, 0, sizeof os_version_info);
- os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- GetVersionEx (&os_version_info);
-
- switch (os_version_info.dwPlatformId)
- {
- case VER_PLATFORM_WIN32_NT:
- os_being_run = winNT;
- os = "NT";
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- if (os_version_info.dwMinorVersion == 0)
- {
- os_being_run = win95;
- os = "95";
- }
- else if (os_version_info.dwMinorVersion < 90)
- {
- os_being_run = win98;
- os = "98";
- }
- else /* os_version_info.dwMinorVersion == 90 */
- {
- os_being_run = winME;
- os = "ME";
- }
- break;
- default:
- os_being_run = unknown;
- os = "??";
- break;
- }
- __small_sprintf (osname, "%s-%d.%d", os, os_version_info.dwMajorVersion,
- os_version_info.dwMinorVersion);
-}
-
-host_dependent_constants NO_COPY host_dependent;
-
-/* Constructor for host_dependent_constants. */
-
-void
-host_dependent_constants::init ()
-{
- extern DWORD chunksize;
- /* fhandler_disk_file::lock needs a platform specific upper word
- value for locking entire files.
-
- fhandler_base::open requires host dependent file sharing
- attributes. */
-
- switch (os_being_run)
- {
- case winNT:
- win32_upper = 0xffffffff;
- shared = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- break;
-
- case winME:
- case win98:
- case win95:
- case win32s:
- win32_upper = 0x00000000;
- shared = FILE_SHARE_READ | FILE_SHARE_WRITE;
- chunksize = 32 * 1024 * 1024;
- break;
-
- default:
- api_fatal ("unrecognized system type");
- }
-}
-
/*
* Replaces -@file in the command line with the contents of the file.
* There may be multiple -@file's in a single command line
int n = 0;
char *p, *s;
int dos_spec = isdrive (word);
- if (!dos_spec && isquote(*word) && word[1] && word[2])
+ if (!dos_spec && isquote (*word) && word[1] && word[2])
dos_spec = isdrive (word + 1);
/* We'll need more space if there are quoting characters in
child_info_fork NO_COPY *child_proc_info = NULL;
static MEMORY_BASIC_INFORMATION sm;
+#define CYGWIN_GUARD ((wincap.has_page_guard ()) ? PAGE_GUARD : PAGE_NOACCESS)
+
// __inline__ void
extern void
alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
{
m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
- PAGE_EXECUTE_READWRITE|PAGE_GUARD))
+ PAGE_EXECUTE_READWRITE|CYGWIN_GUARD))
api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
m.BaseAddress);
}
fork on Win95, but I don't know exactly why yet. DJ */
volatile char b[ci->stacksize + 16384];
- if (ci->type == PROC_FORK)
- ci->stacksize = 0; // flag to fork not to do any funny business
- else
- {
- if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
- api_fatal ("fork: couldn't get stack info, %E");
+ if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
+ api_fatal ("fork: couldn't get stack info, %E");
- if (sm.AllocationBase != ci->stacktop)
- alloc_stack_hard_way (ci, b + sizeof(b) - 1);
- else
- ci->stacksize = 0;
- }
+ if (sm.AllocationBase != ci->stacktop)
+ alloc_stack_hard_way (ci, b + sizeof (b) - 1);
+ else
+ ci->stacksize = 0;
return;
}
static NO_COPY int mypid = 0;
-int _declspec(dllexport) __argc = 0;
-char _declspec(dllexport) **__argv = NULL;
+int _declspec(dllexport) __argc;
+char _declspec(dllexport) **__argv;
+vfork_save NO_COPY *main_vfork = NULL;
void
sigthread::init (const char *s)
/* 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. */
+ /* Initialize SIGSEGV handling, etc. */
init_exceptions (&cygwin_except_entry);
do_global_ctors (&__CTOR_LIST__, 1);
/* Set the os_being_run global. */
- set_os_type ();
+ wincap.init ();
check_sanity_and_sync (user_data);
/* Nasty static stuff needed by newlib -- point to a local copy of
threadname_init ();
debug_init ();
- cygheap_init (); /* Initialize cygheap muto */
+ (void) getpagesize (); /* initialize page size constant */
regthread ("main", GetCurrentThreadId ());
mainthread.init ("mainthread"); // For use in determining if signals
if (child_proc_info)
{
- cygheap = child_proc_info->cygheap;
- cygheap_max = child_proc_info->cygheap_max;
- switch (child_proc_info->type)
+ switch (child_proc_info->type - _cygwin_testing_magic)
{
- case PROC_FORK:
- case PROC_FORK1:
- cygheap_fixup_in_child (child_proc_info->parent, 0);
+ case _PROC_FORK:
+ cygheap_fixup_in_child (child_proc_info, 0);
alloc_stack (fork_info);
set_myself (mypid);
- 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_SPAWN:
- CloseHandle (spawn_info->hexec_proc);
+ case _PROC_SPAWN:
+ if (spawn_info->hexec_proc)
+ CloseHandle (spawn_info->hexec_proc);
goto around;
- case PROC_EXEC:
+ case _PROC_EXEC:
hexec_proc = spawn_info->hexec_proc;
around:
HANDLE h;
- cygheap_fixup_in_child (spawn_info->parent, 1);
+ cygheap_fixup_in_child (spawn_info, 1);
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);
+ myself->uid = spawn_info->moreinfo->uid;
__argc = spawn_info->moreinfo->argc;
__argv = spawn_info->moreinfo->argv;
envp = spawn_info->moreinfo->envp;
envc = spawn_info->moreinfo->envc;
- cygcwd.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);
+ cygheap->fdtab.fixup_after_exec (spawn_info->parent);
signal_fixup_after_exec (child_proc_info->type == PROC_SPAWN);
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);
- myself->uid = spawn_info->moreinfo->uid;
+ if (child_proc_info->subproc_ready)
+ ProtectHandle (child_proc_info->subproc_ready);
if (myself->uid == USHRT_MAX)
- myself->use_psid = 0;
+ cygheap->user.set_sid (NULL);
break;
}
}
ProtectHandle (hMainProc);
ProtectHandle (hMainThread);
- /* Initialize the host dependent constants object. */
- host_dependent.init ();
-
/* Initialize the cygwin subsystem if this is the first process,
- or attach to the shared data structure if it's already running. */
- shared_init ();
+ or attach to shared data structures if it's already running. */
+ memory_init ();
+ cygheap->fdtab.vfork_child_fixup ();
(void) SetErrorMode (SEM_FAILCRITICALERRORS);
- /* Initialize the heap. */
- heap_init ();
-
/* Initialize events. */
events_init ();
- cygcwd.init ();
+ cygheap->cwd.init ();
+ main_vfork = vfork_storage.create ();
cygbench ("pre-forkee");
-
if (user_data->forkee)
{
/* If we've played with the stack, stacksize != 0. That means that
longjmp (fork_info->jmp, fork_info->cygpid);
}
+#ifdef DEBUGGING
+ {
+ extern void fork_init ();
+ fork_init ();
+ }
+#endif
+
/* Initialize our process table entry. */
pinfo_init (envp, envc);
if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
old_title = title_buf;
- /* Allocate fdtab */
+ /* Allocate cygheap->fdtab */
dtable_init ();
/* Initialize uid, gid. */
/* Connect to tty. */
tty_init ();
- /* Set up standard fds in file descriptor table. */
- stdio_init ();
-
if (!__argc)
{
char *line = GetCommandLineA ();
line = strcpy ((char *) alloca (strlen (line) + 1), line);
+ if (current_codepage == oem_cp)
+ CharToOemA (line, line);
+
/* Scan the command line and build argv. Expand wildcards if not
called from another cygwin process. */
build_argv (line, __argv, __argc,
if (user_data->premain[0])
for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
- user_data->premain[i] (__argc, __argv);
+ user_data->premain[i] (__argc, __argv, user_data);
+
+ /* Set up standard fds in file descriptor table. */
+ stdio_init ();
/* Set up __progname for getopt error call. */
__progname = __argv[0];
/* Execute any specified "premain" functions */
if (user_data->premain[PREMAIN_LEN / 2])
for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
- user_data->premain[i] (__argc, __argv);
+ user_data->premain[i] (__argc, __argv, user_data);
debug_printf ("user_data->main %p", user_data->main);
exit (user_data->main (__argc, __argv, *user_data->envptr));
}
+void
+initial_env ()
+{
+ char buf[MAX_PATH + 1];
+#ifdef DEBUGGING
+ if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
+ {
+ console_printf ("Sleeping %d, pid %u\n", atoi (buf), GetCurrentProcessId ());
+ Sleep (atoi (buf));
+ }
+#endif
+
+ if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
+ {
+ _cygwin_testing = 1;
+ DWORD len;
+ if ((len = GetModuleFileName (cygwin_hmodule, buf, MAX_PATH))
+ && len > sizeof ("new-cygwin1.dll")
+ && strcasematch (buf + len - sizeof ("new-cygwin1.dll"),
+ "\\new-cygwin1.dll"))
+ _cygwin_testing_magic = 0x10;
+ }
+}
+
+
/* Wrap the real one, otherwise gdb gets confused about
two symbols with the same name, but different addresses.
extern "C" void __stdcall
_dll_crt0 ()
{
+ DECLARE_TLS_STORAGE;
+ initial_env ();
char zeros[sizeof (fork_info->zero)] = {0};
#ifdef DEBUGGING
strace.microseconds ();
#endif
- /* Set the os_being_run global. */
- set_os_type ();
-
-#ifdef DEBUGGING
- char buf[80];
- if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf)))
- {
- small_printf ("Sleeping %d, pid %u\n", atoi (buf), GetCurrentProcessId ());
- Sleep (atoi(buf));
- }
-#endif
-
main_environ = user_data->envptr;
- user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
+ *main_environ = NULL;
set_console_handler ();
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
hMainProc = GetCurrentProcess ();
DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
- &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
GetStartupInfo (&si);
if (si.cbReserved2 >= EXEC_MAGIC_SIZE &&
memcmp (fork_info->zero, zeros, sizeof (zeros)) == 0)
{
- switch (fork_info->type)
+ switch (fork_info->type - _cygwin_testing_magic)
{
- case PROC_FORK:
- case PROC_FORK1:
+ case _PROC_FORK:
user_data->forkee = fork_info->cygpid;
- case PROC_SPAWN:
- CloseHandle (fork_info->pppid_handle);
- case PROC_EXEC:
+ case _PROC_SPAWN:
+ if (fork_info->pppid_handle)
+ CloseHandle (fork_info->pppid_handle);
+ case _PROC_EXEC:
{
child_proc_info = fork_info;
+ cygwin_mount_h = child_proc_info->mount_h;
mypid = child_proc_info->cygpid;
- cygwin_shared_h = child_proc_info->shared_h;
- console_shared_h = child_proc_info->console_h;
-
- /* We don't want subprocesses to inherit this */
- if (dynamically_loaded)
- parent_alive = NULL;
- else if (!DuplicateHandle (hMainProc, child_proc_info->parent_alive,
- hMainProc, &parent_alive, 0, 0,
- DUPLICATE_SAME_ACCESS
- | DUPLICATE_CLOSE_SOURCE))
- system_printf ("parent_alive DuplicateHandle failed, %E");
-
break;
}
default:
- 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");
+ if (_cygwin_testing)
+ fork_info = NULL;
+ else if ((fork_info->type & PROC_MAGIC_MASK) == PROC_MAGIC_GENERIC)
+ multiple_cygwin_die ();
+ break;
}
}
dll_crt0_1 ();
void
dll_crt0 (per_process *uptr)
{
+ DECLARE_TLS_STORAGE;
/* Set the local copy of the pointer into the user space. */
if (uptr && uptr != user_data)
{
{
static char **envp;
static int _fmode;
- user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
GetCurrentProcess (), &hMainProc, 0, FALSE,
}
/* Kill the foreground process group on session leader exit */
- if (getpgrp () > 0 && myself->pid == myself->sid && tty_attached (myself))
+ if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
{
tty *tp = cygwin_shared->tty[myself->ctty];
sigproc_printf ("%d == sid %d, send SIGHUP to children",
myself->exit (1);
}
+void
+multiple_cygwin_die ()
+{
+ api_fatal ("\
+You have multiple copies of cygwin1.dll on your system.\n\
+Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
+and delete all but the most recent version. This will probably be\n\
+the one that resides in x:\\cygwin\\bin, where 'x' is the drive on which\n\
+you have installed the cygwin distribution.\n");
+}
+
#ifdef DEBUGGING
void __stdcall
cygbench (const char *s)