Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/dcrt0.cc')
-rw-r--r--winsup/cygwin/dcrt0.cc1063
1 files changed, 0 insertions, 1063 deletions
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
deleted file mode 100644
index 10652044e..000000000
--- a/winsup/cygwin/dcrt0.cc
+++ /dev/null
@@ -1,1063 +0,0 @@
-/* dcrt0.cc -- essentially the main() for the Cygwin dll
-
- Copyright 1996, 1997, 1998, 1999, 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 <unistd.h>
-#include <stdlib.h>
-#include "winsup.h"
-#include "glob.h"
-#include "exceptions.h"
-#include "dll_init.h"
-#include "autoload.h"
-#include <ctype.h>
-
-#define MAX_AT_FILE_LEVEL 10
-
-HANDLE NO_COPY hMainProc = NULL;
-HANDLE NO_COPY hMainThread = NULL;
-
-static per_process dummy_user_data = {0};
-per_process NO_COPY *user_data = &dummy_user_data;
-
-per_thread_waitq NO_COPY waitq_storage;
-per_thread_vfork NO_COPY vfork_storage;
-per_thread_signal_dispatch NO_COPY signal_dispatch_storage;
-
-per_thread NO_COPY *threadstuff[] = {&waitq_storage,
- &vfork_storage,
- &signal_dispatch_storage,
- NULL};
-
-BOOL display_title = FALSE;
-BOOL strip_title_path = FALSE;
-BOOL allow_glob = TRUE;
-
-HANDLE NO_COPY parent_alive = NULL;
-
-/* 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.
- In older versions of cygwin, the signal was used as-is to shift the
- 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;
-
-extern "C"
-{
- /* This is an exported copy of environ which can be used by DLLs
- which use cygwin.dll. */
- char **__cygwin_environ;
- /* __progname used in getopt error message */
- char *__progname;
- struct _reent reent_data;
-};
-
-static void dll_crt0_1 ();
-
-char *old_title = NULL;
-char title_buf[TITLESIZE + 1];
-
-static void
-do_global_dtors (void)
-{
- if (user_data->dtors)
- {
- void (**pfunc)() = user_data->dtors;
- while (*++pfunc)
- (*pfunc) ();
- }
-}
-
-static void __stdcall
-do_global_ctors (void (**in_pfunc)(), int force)
-{
- if (!force)
- {
- if (user_data->forkee || user_data->run_ctors_p)
- return; // inherit constructed stuff from parent pid
- user_data->run_ctors_p = 1;
- }
-
- /* Run ctors backwards, so skip the first entry and find how many
- there are, then run them. */
-
- void (**pfunc)() = in_pfunc;
-
- while (*++pfunc)
- ;
- while (--pfunc > in_pfunc)
- (*pfunc) ();
-
- if (user_data != &dummy_user_data)
- atexit (do_global_dtors);
-}
-
-/* remember the type of Win32 OS being run for future use. */
-os_type NO_COPY os_being_run;
-
-/* 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;
- os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
-
- GetVersionEx (&os_version_info);
-
- switch (os_version_info.dwPlatformId)
- {
- case VER_PLATFORM_WIN32_NT:
- os_being_run = winNT;
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- if (os_version_info.dwMinorVersion == 0)
- os_being_run = win95;
- else /* os_version_info.dwMinorVersion == 10 */
- os_being_run = win98;
- break;
- case VER_PLATFORM_WIN32s:
- os_being_run = win32s;
- break;
- default:
- os_being_run = unknown;
- break;
- }
-}
-
-host_dependent_constants NO_COPY host_dependent;
-
-/* Constructor for host_dependent_constants. */
-
-void
-host_dependent_constants::init (void)
-{
- /* 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 win98:
- case win95:
- case win32s:
- win32_upper = 0x00000000;
- shared = FILE_SHARE_READ | FILE_SHARE_WRITE;
- break;
-
- default:
- api_fatal ("unrecognized system type");
- }
-}
-
-/* Save the program name. It's used in debugging messages and by
- the fork code (forking spawns a copy of us). Copy it into a temp and
- then into the final spot because debugging messages use
- myself->progname. Try getting the absolute path from the
- module handle, if this fails get the name from the path.
- This call references $PATH so we can't do this until the environment
- vars are set up. */
-/* FIXME: What if argv[0] is relative, $PATH changes, and then the program
- tries to do a fork? */
-
-static void __stdcall
-getprogname (char *argv0)
-{
- char tmp[MAX_PATH];
-
- if (user_data->hmodule != 0)
- {
- if (GetModuleFileName (user_data->hmodule, tmp, MAX_PATH) == 0)
- find_exec (argv0, tmp);
- }
- else
- find_exec (argv0, tmp);
- strcpy (myself->progname, tmp);
-}
-
-/*
- * Replaces -@file in the command line with the contents of the file.
- * There may be multiple -@file's in a single command line
- * A \-@file is replaced with -@file so that echo \-@foo would print
- * -@foo and not the contents of foo.
- */
-static int __stdcall
-insert_file (char *name, char *&cmd)
-{
- HANDLE f;
- DWORD size;
-
- f = CreateFile (name + 1,
- GENERIC_READ, /* open for reading */
- FILE_SHARE_READ, /* share for reading */
- &sec_none_nih, /* no security */
- OPEN_EXISTING, /* existing file only */
- FILE_ATTRIBUTE_NORMAL, /* normal file */
- NULL); /* no attr. template */
-
- if (f == INVALID_HANDLE_VALUE)
- {
- debug_printf ("couldn't open file '%s', %E", name);
- return FALSE;
- }
-
- /* This only supports files up to about 4 billion bytes in
- size. I am making the bold assumption that this is big
- enough for this feature */
- size = GetFileSize (f, NULL);
- if (size == 0xFFFFFFFF)
- {
- debug_printf ("couldn't get file size for '%s', %E", name);
- return FALSE;
- }
-
- int new_size = strlen (cmd) + size + 2;
- char *tmp = (char *) malloc (new_size);
- if (!tmp)
- {
- debug_printf ("malloc failed, %E");
- return FALSE;
- }
-
- /* realloc passed as it should */
- DWORD rf_read;
- BOOL rf_result;
- rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
- CloseHandle (f);
- if (!rf_result || (rf_read != size))
- {
- debug_printf ("ReadFile failed, %E");
- return FALSE;
- }
-
- tmp[size++] = ' ';
- strcpy (tmp + size, cmd);
- cmd = tmp;
- return TRUE;
-}
-
-static inline int
-isquote (char c)
-{
- char ch = c;
- return ch == '"' || ch == '\'';
-}
-
-/* Step over a run of characters delimited by quotes */
-static __inline char *
-quoted (char *word, char *cmd, int winshell)
-{
- char *p;
- char quote = *cmd;
-
- /* If this is being run from a Windows shell then we have
- to preserve quotes for globify to play with later. */
- if (winshell)
- {
- while (*++cmd)
- if ((p = strchr (cmd, quote)) == NULL)
- {
- cmd = strchr (cmd, '\0'); // no closing quote
- break;
- }
- else if (p[1] == quote)
- {
- *p++ = '\\';
- cmd = p; // a quoted quote
- }
- else
- {
- cmd = p + 1; // point to after end
- break;
- }
- return cmd;
- }
-
- /* When running as a child of a cygwin process, the quoted
- 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 \ */
- strcpy (cmd, cmd + 1);
- while (*cmd)
- {
- if (*cmd != quote)
- cmd++;
- else if (cmd[1] == quote)
- strcpy (cmd++, cmd + 1);
- else
- {
- strcpy (cmd, cmd + 1);
- break;
- }
- }
- return cmd;
-}
-
-/* Perform a glob on word if it contains wildcard characters.
- Also quote every character between quotes to force glob to
- treat the characters literally. */
-static int __stdcall
-globify (char *word, char **&argv, int &argc, int &argvlen)
-{
- if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
- return 0;
-
- int n = 0;
- char *p, *s;
- int dos_spec = isalpha(*word) && word[1] == ':' ? 1 : 0;
-
- /* We'll need more space if there are quoting characters in
- word. If that is the case, doubling the size of the
- string should provide more than enough space. */
- if (strpbrk (word, "'\""))
- n = strlen (word);
- char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
-
- /* Fill pattern with characters from word, quoting any
- characters found within quotes. */
- for (p = pattern, s = word; *s != '\000'; s++, p++)
- if (!isquote (*s))
- {
- if (dos_spec && *s == '\\')
- *p++ = '\\';
- *p = *s;
- }
- else
- {
- char quote = *s;
- while (*++s && *s != quote)
- {
- if (*s == '\\' && s[1] == quote)
- s++;
- *p++ = '\\';
- *p++ = *s;
- }
- if (*s == quote)
- p--;
- if (*s == '\0')
- break;
- }
-
- *p = '\0';
-
- glob_t gl;
- gl.gl_offs = 0;
-
- /* Attempt to match the argument. Return just word (minus quoting) if no match. */
- if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
- return 0;
-
- /* Allocate enough space in argv for the matched filenames. */
- n = argc;
- if ((argc += gl.gl_pathc) > argvlen)
- {
- argvlen = argc + 10;
- argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
- }
-
- /* Copy the matched filenames to argv. */
- char **gv = gl.gl_pathv;
- char **av = argv + n;
- while (*gv)
- {
- debug_printf ("argv[%d] = '%s'\n", n++, *gv);
- *av++ = *gv++;
- }
-
- /* Clean up after glob. */
- free (gl.gl_pathv);
- return 1;
-}
-
-/* Build argv, argc from string passed from Windows. */
-
-static void __stdcall
-build_argv (char *cmd, char **&argv, int &argc, int winshell)
-{
- int argvlen = 0;
- char *alloc_cmd = NULL; // command allocated by insert_file
- int nesting = 0; // monitor "nesting" from insert_file
-
- argc = 0;
- argvlen = 0;
- argv = NULL;
-
- /* Scan command line until there is nothing left. */
- while (*cmd)
- {
- /* Ignore spaces */
- if (issep (*cmd))
- {
- cmd++;
- continue;
- }
-
- /* Found the beginning of an argument. */
- char *word = cmd;
- char *sawquote = NULL;
- while (*cmd)
- {
- if (*cmd != '"' && (!winshell || *cmd != '\''))
- cmd++; // Skip over this character
- else
- /* Skip over characters until the closing quote */
- {
- sawquote = cmd;
- cmd = quoted (word, cmd, winshell);
- }
- if (issep (*cmd)) // End of argument if space
- break;
- }
- if (*cmd)
- *cmd++ = '\0'; // Terminate `word'
-
- /* Possibly look for @file construction assuming that this isn't
- the very first argument and the @ wasn't quoted */
- if (argc && sawquote != word && *word == '@')
- {
- if (++nesting > MAX_AT_FILE_LEVEL)
- api_fatal ("Too many levels of nesting for %s", word);
- if (insert_file (word, cmd))
- {
- if (alloc_cmd)
- free (alloc_cmd); // Free space from previous insert_file
- alloc_cmd = cmd; // and remember it for next time.
- continue; // There's new stuff in cmd now
- }
- }
-
- /* See if we need to allocate more space for argv */
- if (argc >= argvlen)
- {
- argvlen = argc + 10;
- argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
- }
-
- /* Add word to argv file after (optional) wildcard expansion. */
- if (!winshell || !argc || !globify (word, argv, argc, argvlen))
- {
- debug_printf ("argv[%d] = '%s'\n", argc, word);
- argv[argc++] = word;
- }
- }
-
- argv[argc] = NULL;
- debug_printf ("argv[%d] = '%s'\n", argc, argv[argc]);
-}
-
-/* sanity and sync check */
-void __stdcall
-check_sanity_and_sync (per_process *p)
-{
- /* Sanity check to make sure developers didn't change the per_process */
- /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
- /* about changing it]. */
- if (sizeof (per_process) != SIZEOF_PER_PROCESS)
- {
- api_fatal ("per_process sanity check failed");
- }
-
- /* Make sure that the app and the dll are in sync. */
-
- /* Complain if older than last incompatible change */
- if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
- api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
- p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
-
- /* magic_biscuit != 0 if using the old style version numbering scheme. */
- if (p->magic_biscuit != SIZEOF_PER_PROCESS)
- api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
- p->magic_biscuit, SIZEOF_PER_PROCESS);
-
- /* Complain if incompatible API changes made */
- if (p->api_major != cygwin_version.api_major)
- api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d < %d",
- p->api_major, cygwin_version.api_major);
-
- if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
- CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
- signal_shift_subtract = 0;
-}
-
-static NO_COPY STARTUPINFO si;
-# define ciresrv ((struct child_info_fork *)(si.lpReserved2))
-child_info_fork NO_COPY *child_proc_info = NULL;
-static MEMORY_BASIC_INFORMATION sm;
-
-#define EBP 6
-#define ESP 7
-
-extern void __inline__
-alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
-{
- void *new_stack_pointer;
- MEMORY_BASIC_INFORMATION m;
-
- if (!VirtualAlloc (ci->stacktop,
- (DWORD) ci->stackbottom - (DWORD) ci->stacktop,
- MEM_RESERVE, PAGE_NOACCESS))
- api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
- ci->stacktop, ci->stackbottom);
-
- new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
-
- if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
- PAGE_EXECUTE_READWRITE))
- api_fatal ("fork: can't commit memory for stack %p(%d), %E",
- new_stack_pointer, ci->stacksize);
- if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
- api_fatal ("fork: couldn't get new stack info, %E");
- m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
- if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
- PAGE_EXECUTE_READWRITE|PAGE_GUARD))
- api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
- m.BaseAddress);
- if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
- api_fatal ("fork: couldn't get new stack info, %E");
- ci->stacktop = m.BaseAddress;
- *b = 0;
-}
-
-/* extend the stack prior to fork longjmp */
-
-extern void __inline__
-alloc_stack (child_info_fork *ci)
-{
- /* FIXME: adding 16384 seems to avoid a stack copy problem during
- 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 (sm.AllocationBase != ci->stacktop)
- alloc_stack_hard_way (ci, b + sizeof(b) - 1);
- else
- ci->stacksize = 0;
- }
-
- return;
-}
-
-/* These must be static due to the way we have to deal with forked
- processes. */
-static NO_COPY LPBYTE info = NULL;
-static NO_COPY int mypid = 0;
-static int argc = 0;
-static char **argv = NULL;
-
-#ifdef _MT_SAFE
-ResourceLocks _reslock NO_COPY;
-MTinterface _mtinterf NO_COPY;
-#endif
-
-/* Take over from libc's crt0.o and start the application. Note the
- various special cases when Cygwin DLL is being runtime loaded (as
- opposed to being link-time loaded by Cygwin apps) from a non
- cygwin app via LoadLibrary. */
-static void
-dll_crt0_1 ()
-{
- /* 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;
-
- do_global_ctors (&__CTOR_LIST__, 1);
-
-#ifdef DEBUGGING
- if (child_proc_info)
- switch (child_proc_info->type)
- {
- case PROC_FORK:
- case PROC_FORK1:
- ProtectHandle (child_proc_info->forker_finished);
- case PROC_EXEC:
- ProtectHandle (child_proc_info->subproc_ready);
- }
- ProtectHandle (hMainProc);
- ProtectHandle (hMainThread);
-#endif
-
- regthread ("main", GetCurrentThreadId ());
-
- check_sanity_and_sync (user_data);
-
- /* Nasty static stuff needed by newlib -- point to a local copy of
- the reent stuff.
- Note: this MUST be done here (before the forkee code) as the
- fork copy code doesn't copy the data in libccrt0.cc (that's why we
- pass in the per_process struct into the .dll from libccrt0). */
-
- *(user_data->impure_ptr_ptr) = &reent_data;
- _impure_ptr = &reent_data;
-
-#ifdef _MT_SAFE
- user_data->resourcelocks = &_reslock;
- user_data->resourcelocks->Init();
-
- user_data->threadinterface = &_mtinterf;
- user_data->threadinterface->Init0();
-#endif
-
- /* Set the os_being_run global. */
- set_os_type ();
-
- /* If we didn't call SetFileApisToOEM, console I/O calls would use a
- different codepage than other Win32 API calls. In some languages
- (not English), this would result in "cat > filename" creating a file
- by a different name than if CreateFile was used to create filename.
- SetFileApisToOEM prevents this problem by making all calls use the
- OEM codepage. */
-
- SetFileApisToOEM ();
-
- /* 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 ();
-
- if (mypid)
- set_myself (cygwin_shared->p[mypid]);
-
- (void) SetErrorMode (SEM_FAILCRITICALERRORS);
-
- /* Initialize the heap. */
- heap_init ();
-
- /* Initialize events. */
- events_init ();
-
- threadname_init ();
- debug_init ();
-
- /* 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);
-
- if (user_data->forkee)
- {
- /* If we've played with the stack, stacksize != 0. That means that
- fork() was invoked from other than the main thread. Make sure that
- frame pointer is referencing the new stack so that the OS knows what
- to do when it needs to increase the size of the stack.
-
- NOTE: Don't do anything that involves the stack until you've completed
- this step. */
- if (ciresrv->stacksize)
- {
- asm ("movl %0,%%fs:4" : : "r" (ciresrv->stackbottom));
- asm ("movl %0,%%fs:8" : : "r" (ciresrv->stacktop));
- }
-
- longjmp (ciresrv->jmp, ciresrv->cygpid);
- }
-
- /* Initialize our process table entry. Don't use the parent info for
- dynamically loaded case. */
- pinfo_init ((dynamically_loaded) ? NULL : info);
-
- if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
- old_title = title_buf;
-
- /* Nasty static stuff needed by newlib - initialize it.
- Note that impure_ptr has already been set up to point to this above
- NB. This *MUST* be done here, just after the forkee code as some
- of the calls below (eg. uinfo_init) do stdio calls - this area must
- be set to zero before then. */
-
-#ifdef _MT_SAFE
- user_data->threadinterface->ClearReent();
- user_data->threadinterface->Init1();
-#else
- memset (&reent_data, 0, sizeof (reent_data));
- reent_data._errno = 0;
- reent_data._stdin = reent_data.__sf + 0;
- reent_data._stdout = reent_data.__sf + 1;
- reent_data._stderr = reent_data.__sf + 2;
-#endif
-
- char *line = GetCommandLineA ();
- CharToOem (line, line);
-
- line = strcpy ((char *) alloca (strlen (line) + 1), line);
-
- /* Set new console title if appropriate. */
-
- if (display_title && !dynamically_loaded)
- {
- char *cp = line;
- if (strip_title_path)
- for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
- if (isdirsep (*ptr))
- cp = ptr + 1;
- set_console_title (cp);
- }
-
- /* Allocate dtable */
- dtable_init ();
-
- /* Initialize signal/subprocess handling. */
- sigproc_init ();
-
- /* Connect to tty. */
- tty_init ();
-
- /* Set up standard fds in file descriptor table. */
- hinfo_init ();
-
-#if 0
- /* Initialize uid, gid. */
- uinfo_init ();
-#endif
-
- syscall_printf ("Application CYGWIN version: %d.%d, api: %d.%d",
- user_data->dll_major, user_data->dll_minor,
- user_data->api_major, user_data->api_minor);
- syscall_printf ("CYGWIN DLL version: %d.%d, api: %d.%d",
- cygwin_version.dll_major, cygwin_version.dll_minor,
- cygwin_version.api_major, cygwin_version.api_minor);
-
- /* Scan the command line and build argv. Expand wildcards if not
- called from another cygwin process. */
- build_argv (line, argv, argc,
- NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
-
- /* Convert argv[0] to posix rules if it's currently blatantly
- win32 style. */
- if ((strchr (argv[0], ':')) || (strchr (argv[0], '\\')))
- {
- char *new_argv0 = (char *) alloca (MAX_PATH);
- cygwin_conv_to_posix_path (argv[0], new_argv0);
- argv[0] = new_argv0;
- }
-
- getprogname (argv[0]);
- /* Set up __progname for getopt error call. */
- __progname = argv[0];
-
- /* Call init of loaded dlls. */
- DllList::the().initAll();
-
- set_errno (0);
- debug_printf ("user_data->main %p", user_data->main);
-
- /* Flush signals and ensure that signal thread is up and running. Can't
- do this for noncygwin case since the signal thread is blocked due to
- LoadLibrary serialization. */
- if (!dynamically_loaded)
- sig_send (NULL, __SIGFLUSH);
-
- /* Initialize uid, gid. */
- uinfo_init ();
-
- if (user_data->main && !dynamically_loaded)
- exit (user_data->main (argc, argv, *user_data->envptr));
-}
-
-/* Wrap the real one, otherwise gdb gets confused about
- two symbols with the same name, but different addresses.
-
- UPTR is a pointer to global data that lives on the libc side of the
- line [if one distinguishes the application from the dll]. */
-
-void
-dll_crt0 (per_process *uptr)
-{
- char zeros[sizeof (ciresrv->zero)] = {0};
- /* Set the local copy of the pointer into the user space. */
- user_data = uptr;
- user_data->heapbase = user_data->heapptr = user_data->heaptop = NULL;
-
- set_console_handler ();
- if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
- GetCurrentProcess (), &hMainProc, 0, FALSE,
- DUPLICATE_SAME_ACCESS))
- hMainProc = GetCurrentProcess ();
-
- DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
- &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
-
- GetStartupInfo (&si);
- if (si.cbReserved2 >= EXEC_MAGIC_SIZE &&
- memcmp (ciresrv->zero, zeros, sizeof (zeros)) == 0)
- {
- switch (ciresrv->type)
- {
- case PROC_EXEC:
- case PROC_SPAWN:
- case PROC_FORK:
- case PROC_FORK1:
- {
- HANDLE me = hMainProc;
- child_proc_info = ciresrv;
- mypid = child_proc_info->cygpid;
- cygwin_shared_h = child_proc_info->shared_h;
- console_shared_h = child_proc_info->console_h;
-
- /* We don't want subprocesses to inherit this */
- if (!dynamically_loaded)
- {
- if (!DuplicateHandle (me, child_proc_info->parent_alive,
- me, &parent_alive, 0, 0,
- DUPLICATE_SAME_ACCESS
- | DUPLICATE_CLOSE_SOURCE))
- system_printf ("parent_alive DuplicateHandle failed, %E");
- }
- else if (parent_alive)
- parent_alive = NULL;
-
- switch (child_proc_info->type)
- {
- case PROC_EXEC:
- case PROC_SPAWN:
- info = si.lpReserved2 + ciresrv->cb;
- break;
- case PROC_FORK:
- case PROC_FORK1:
- user_data->forkee = child_proc_info->cygpid;
- user_data->heaptop = child_proc_info->heaptop;
- user_data->heapbase = child_proc_info->heapbase;
- user_data->heapptr = child_proc_info->heapptr;
- alloc_stack (ciresrv); // may never return
- }
- break;
- }
- default:
- if ((ciresrv->type & PROC_MAGIC_MASK) == PROC_MAGIC_GENERIC)
- api_fatal ("conflicting versions of cygwin1.dll detected. Use only the most recent version.\n");
- }
- }
- dll_crt0_1 ();
-}
-
-extern "C" void
-__main (void)
-{
- do_global_ctors (user_data->ctors, FALSE);
-}
-
-enum
- {
- ES_SIGNAL = 1,
- ES_CLOSEALL = 2,
- ES_SIGPROCTERMINATE = 3
- };
-
-extern "C" void __stdcall
-do_exit (int status)
-{
- BOOL cleanup_pinfo;
- UINT n = (UINT) status;
- static int NO_COPY exit_state = 0;
-
- syscall_printf ("do_exit (%d)", n);
-
- vfork_save *vf = vfork_storage.val ();
- if (vf != NULL && vf->pid < 0)
- {
- vf->pid = status < 0 ? status : -status;
- longjmp (vf->j, 1);
- }
-
- if (exit_state < ES_SIGNAL)
- {
- exit_state = ES_SIGNAL;
- if (!(n & EXIT_REPARENTING))
- {
- signal (SIGCHLD, SIG_IGN);
- signal (SIGHUP, SIG_IGN);
- signal (SIGINT, SIG_IGN);
- signal (SIGQUIT, SIG_IGN);
- }
- }
-
- if ((hExeced && hExeced != INVALID_HANDLE_VALUE) || (n & EXIT_NOCLOSEALL))
- n &= ~EXIT_NOCLOSEALL;
- else if (exit_state < ES_CLOSEALL)
- {
- exit_state = ES_CLOSEALL;
- close_all_files ();
- }
-
- if (exit_state < ES_SIGPROCTERMINATE)
- {
- exit_state = ES_SIGPROCTERMINATE;
- sigproc_terminate ();
- }
-
- if (n & EXIT_REPARENTING)
- {
- n &= ~EXIT_REPARENTING;
- cleanup_pinfo = FALSE;
- }
- else
- {
- myself->stopsig = 0;
-
- /* restore console title */
- if (old_title && display_title)
- set_console_title (old_title);
-
- /* Kill orphaned children on group leader exit */
- if (myself->pid == myself->pgid)
- {
- sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
- myself->pid, myself->pgid);
- kill_pgrp (myself->pgid, -SIGHUP);
- }
-
- /* Kill the foreground process group on session leader exit */
- if (getpgrp () > 0 && myself->pid == myself->sid && tty_attached (myself))
- {
- tty *tp = cygwin_shared->tty[myself->ctty];
- sigproc_printf ("%d == sid %d, send SIGHUP to children",
- myself->pid, myself->sid);
-
- if (tp->getsid () == myself->sid)
- kill (-tp->getpgid (), SIGHUP);
- }
- tty_terminate ();
- cleanup_pinfo = TRUE;
- }
-
- window_terminate ();
- fill_rusage (&myself->rusage_self, hMainProc);
-
- events_terminate ();
-
- if (hExeced && hExeced != INVALID_HANDLE_VALUE)
- {
- debug_printf ("Killing(%d) non-cygwin process, handle %p", n, hExeced);
- TerminateProcess (hExeced, n);
- ForceCloseHandle1 (hExeced, childhProc);
- }
-
- if (cleanup_pinfo)
- myself->record_death (); // Locks pinfo mutex
- else
- sigproc_printf ("not cleanup_pinfo");
-
- shared_terminate ();
-
- sigproc_printf ("calling ExitProcess %d", n);
- minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
- ExitProcess (n);
-}
-
-extern "C" void
-_exit (int n)
-{
- do_exit ((DWORD) n & 0xffff);
-}
-
-extern "C" void
-__api_fatal (const char *fmt, ...)
-{
- char buf[4096];
- va_list ap;
-
- va_start (ap, fmt);
- __small_vsprintf (buf, fmt, ap);
- va_end (ap);
- small_printf ("%s\n", buf);
-
- /* We are going down without mercy. Make sure we reset
- our process_state. */
- if (user_data != NULL)
- {
- sigproc_terminate ();
- myself->record_death (FALSE);
- }
-#ifdef DEBUGGING
- (void) try_to_debug ();
-#endif
- ExitProcess (1);
-}
-
-extern "C" {
-static void noload (char *s) __asm__ ("noload");
-static void __attribute__((unused))
-noload (char *s)
-{
- api_fatal ("couldn't dynamically determine load address for '%s', %E", s);
-}
-
-__asm__ ("
-.globl cygwin_dll_func_load
-cygwin_dll_func_load:
- movl (%esp),%eax # 'Return address' contains load info
- addl $8,%eax # Address of name of function to load
- pushl %eax # Second argument
- movl -4(%eax),%eax # Address of Handle to DLL
- pushl (%eax) # Handle to DLL
- call _GetProcAddress@8# Load it
- test %eax,%eax # Success?
- jne gotit # Yes
- popl %eax # No. Get back
- addl $8,%eax # pointer to name
- pushl %eax # and
- call noload # issue an error
-gotit:
- popl %ecx # Pointer to 'return address'
- movb $0xe0,-1(%ecx) # Turn preceding call to a jmp *%eax
- movl %eax,(%ecx) # Point dispatch to address loaded above
- jmp *%eax
-");
-}
-
-LoadDLLinitfunc (user32)
-{
- HANDLE h;
-
- if ((h = LoadLibrary ("user32.dll")) != NULL)
- user32_handle = h;
- else if (!user32_handle)
- api_fatal ("could not load user32.dll, %E");
-
- return 0; /* Already done by another thread? */
-}
-
-LoadDLLinit (user32)
-LoadDLLfunc (CharToOemA, CharToOemA@8, user32)
-LoadDLLfunc (CreateWindowExA, CreateWindowExA@48, user32)
-LoadDLLfunc (DefWindowProcA, DefWindowProcA@16, user32)
-LoadDLLfunc (DispatchMessageA, DispatchMessageA@4, user32)
-LoadDLLfunc (FindWindowA, FindWindowA@8, user32)
-LoadDLLfunc (GetMessageA, GetMessageA@16, user32)
-LoadDLLfunc (GetProcessWindowStation, GetProcessWindowStation@0, user32)
-LoadDLLfunc (GetThreadDesktop, GetThreadDesktop@4, user32)
-LoadDLLfunc (GetUserObjectInformationA, GetUserObjectInformationA@20, user32)
-LoadDLLfunc (KillTimer, KillTimer@8, user32)
-LoadDLLfunc (MessageBoxA, MessageBoxA@16, user32)
-LoadDLLfunc (MsgWaitForMultipleObjects, MsgWaitForMultipleObjects@20, user32)
-LoadDLLfunc (OemToCharW, OemToCharW@8, user32)
-LoadDLLfunc (PeekMessageA, PeekMessageA@20, user32)
-LoadDLLfunc (PostMessageA, PostMessageA@16, user32)
-LoadDLLfunc (PostQuitMessage, PostQuitMessage@4, user32)
-LoadDLLfunc (RegisterClassA, RegisterClassA@4, user32)
-LoadDLLfunc (SendMessageA, SendMessageA@16, user32)
-LoadDLLfunc (SetTimer, SetTimer@16, user32)
-LoadDLLfunc (SetUserObjectSecurity, SetUserObjectSecurity@12, user32)