OSDN Git Service

cygwin:
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / dcrt0.cc
1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4    2007, 2008, 2009, 2010
5    Red Hat, Inc.
6
7 This file is part of Cygwin.
8
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
11 details. */
12
13 #include "winsup.h"
14 #include "miscfuncs.h"
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include "glob.h"
18 #include <ctype.h>
19 #include <locale.h>
20 #include "environ.h"
21 #include "sigproc.h"
22 #include "pinfo.h"
23 #include "cygerrno.h"
24 #define NEED_VFORK
25 #include "perprocess.h"
26 #include "path.h"
27 #include "fhandler.h"
28 #include "dtable.h"
29 #include "cygheap.h"
30 #include "child_info_magic.h"
31 #include "cygtls.h"
32 #include "shared_info.h"
33 #include "cygwin_version.h"
34 #include "dll_init.h"
35 #include "heap.h"
36 #include "tls_pbuf.h"
37 #include "exception.h"
38 #include "cygxdr.h"
39 #include "ntdll.h"
40
41 #define MAX_AT_FILE_LEVEL 10
42
43 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
44
45 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
46 extern "C" void __sinit (_reent *);
47
48 static int NO_COPY envc;
49 static char NO_COPY **envp;
50
51 static char title_buf[TITLESIZE + 1];
52
53 bool NO_COPY jit_debug;
54
55 static void
56 do_global_dtors ()
57 {
58   void (**pfunc) () = user_data->dtors;
59   if (pfunc)
60     {
61       user_data->dtors = NULL;
62       while (*++pfunc)
63         (*pfunc) ();
64     }
65 }
66
67 static void __stdcall
68 do_global_ctors (void (**in_pfunc)(), int force)
69 {
70   if (!force && in_forkee)
71     return;             // inherit constructed stuff from parent pid
72
73   /* Run ctors backwards, so skip the first entry and find how many
74      there are, then run them. */
75
76   void (**pfunc) () = in_pfunc;
77
78   while (*++pfunc)
79     ;
80   while (--pfunc > in_pfunc)
81     (*pfunc) ();
82 }
83
84 /*
85  * Replaces @file in the command line with the contents of the file.
86  * There may be multiple @file's in a single command line
87  * A \@file is replaced with @file so that echo \@foo would print
88  * @foo and not the contents of foo.
89  */
90 static bool __stdcall
91 insert_file (char *name, char *&cmd)
92 {
93   HANDLE f;
94   DWORD size;
95   tmp_pathbuf tp;
96
97   PWCHAR wname = tp.w_get ();
98   sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
99   f = CreateFileW (wname,
100                    GENERIC_READ,         /* open for reading    */
101                    FILE_SHARE_READ,      /* share for reading   */
102                    &sec_none_nih,        /* default security    */
103                    OPEN_EXISTING,        /* existing file only  */
104                    FILE_ATTRIBUTE_NORMAL,/* normal file         */
105                    NULL);                /* no attr. template   */
106
107   if (f == INVALID_HANDLE_VALUE)
108     {
109       debug_printf ("couldn't open file '%s', %E", name);
110       return false;
111     }
112
113   /* This only supports files up to about 4 billion bytes in
114      size.  I am making the bold assumption that this is big
115      enough for this feature */
116   size = GetFileSize (f, NULL);
117   if (size == 0xFFFFFFFF)
118     {
119       debug_printf ("couldn't get file size for '%s', %E", name);
120       return false;
121     }
122
123   int new_size = strlen (cmd) + size + 2;
124   char *tmp = (char *) malloc (new_size);
125   if (!tmp)
126     {
127       debug_printf ("malloc failed, %E");
128       return false;
129     }
130
131   /* realloc passed as it should */
132   DWORD rf_read;
133   BOOL rf_result;
134   rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
135   CloseHandle (f);
136   if (!rf_result || (rf_read != size))
137     {
138       debug_printf ("ReadFile failed, %E");
139       return false;
140     }
141
142   tmp[size++] = ' ';
143   strcpy (tmp + size, cmd);
144   cmd = tmp;
145   return true;
146 }
147
148 static inline int
149 isquote (char c)
150 {
151   char ch = c;
152   return ch == '"' || ch == '\'';
153 }
154
155 /* Step over a run of characters delimited by quotes */
156 static /*__inline*/ char *
157 quoted (char *cmd, int winshell)
158 {
159   char *p;
160   char quote = *cmd;
161
162   if (!winshell)
163     {
164       char *p;
165       strcpy (cmd, cmd + 1);
166       if (*(p = strechr (cmd, quote)))
167         strcpy (p, p + 1);
168       return p;
169     }
170
171   const char *s = quote == '\'' ? "'" : "\\\"";
172   /* This must have been run from a Windows shell, so preserve
173      quotes for globify to play with later. */
174   while (*cmd && *++cmd)
175     if ((p = strpbrk (cmd, s)) == NULL)
176       {
177         cmd = strchr (cmd, '\0');       // no closing quote
178         break;
179       }
180     else if (*p == '\\')
181       cmd = ++p;
182     else if (quote == '"' && p[1] == '"')
183       {
184         *p = '\\';
185         cmd = ++p;                      // a quoted quote
186       }
187     else
188       {
189         cmd = p + 1;            // point to after end
190         break;
191       }
192   return cmd;
193 }
194
195 /* Perform a glob on word if it contains wildcard characters.
196    Also quote every character between quotes to force glob to
197    treat the characters literally. */
198 static int __stdcall
199 globify (char *word, char **&argv, int &argc, int &argvlen)
200 {
201   if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
202     return 0;
203
204   int n = 0;
205   char *p, *s;
206   int dos_spec = isdrive (word);
207   if (!dos_spec && isquote (*word) && word[1] && word[2])
208     dos_spec = isdrive (word + 1);
209
210   /* We'll need more space if there are quoting characters in
211      word.  If that is the case, doubling the size of the
212      string should provide more than enough space. */
213   if (strpbrk (word, "'\""))
214     n = strlen (word);
215   char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
216
217   /* Fill pattern with characters from word, quoting any
218      characters found within quotes. */
219   for (p = pattern, s = word; *s != '\000'; s++, p++)
220     if (!isquote (*s))
221       {
222         if (dos_spec && *s == '\\')
223           *p++ = '\\';
224         *p = *s;
225       }
226     else
227       {
228         char quote = *s;
229         while (*++s && *s != quote)
230           {
231             if (dos_spec || *s != '\\')
232               /* nothing */;
233             else if (s[1] == quote || s[1] == '\\')
234               s++;
235             *p++ = '\\';
236             size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
237             if (cnt <= 1 || cnt == (size_t)-1)
238               *p++ = *s;
239             else
240               {
241                 --s;
242                 while (cnt-- > 0)
243                   *p++ = *++s;
244               }
245           }
246         if (*s == quote)
247           p--;
248         if (*s == '\0')
249             break;
250       }
251
252   *p = '\0';
253
254   glob_t gl;
255   gl.gl_offs = 0;
256
257   /* Attempt to match the argument.  Return just word (minus quoting) if no match. */
258   if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
259     return 0;
260
261   /* Allocate enough space in argv for the matched filenames. */
262   n = argc;
263   if ((argc += gl.gl_pathc) > argvlen)
264     {
265       argvlen = argc + 10;
266       argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
267     }
268
269   /* Copy the matched filenames to argv. */
270   char **gv = gl.gl_pathv;
271   char **av = argv + n;
272   while (*gv)
273     {
274       debug_printf ("argv[%d] = '%s'", n++, *gv);
275       *av++ = *gv++;
276     }
277
278   /* Clean up after glob. */
279   free (gl.gl_pathv);
280   return 1;
281 }
282
283 /* Build argv, argc from string passed from Windows.  */
284
285 static void __stdcall
286 build_argv (char *cmd, char **&argv, int &argc, int winshell)
287 {
288   int argvlen = 0;
289   int nesting = 0;              // monitor "nesting" from insert_file
290
291   argc = 0;
292   argvlen = 0;
293   argv = NULL;
294
295   /* Scan command line until there is nothing left. */
296   while (*cmd)
297     {
298       /* Ignore spaces */
299       if (issep (*cmd))
300         {
301           cmd++;
302           continue;
303         }
304
305       /* Found the beginning of an argument. */
306       char *word = cmd;
307       char *sawquote = NULL;
308       while (*cmd)
309         {
310           if (*cmd != '"' && (!winshell || *cmd != '\''))
311             cmd++;              // Skip over this character
312           else
313             /* Skip over characters until the closing quote */
314             {
315               sawquote = cmd;
316               cmd = quoted (cmd, winshell && argc > 0);
317             }
318           if (issep (*cmd))     // End of argument if space
319             break;
320         }
321       if (*cmd)
322         *cmd++ = '\0';          // Terminate `word'
323
324       /* Possibly look for @file construction assuming that this isn't
325          the very first argument and the @ wasn't quoted */
326       if (argc && sawquote != word && *word == '@')
327         {
328           if (++nesting > MAX_AT_FILE_LEVEL)
329             api_fatal ("Too many levels of nesting for %s", word);
330           if (insert_file (word, cmd))
331               continue;                 // There's new stuff in cmd now
332         }
333
334       /* See if we need to allocate more space for argv */
335       if (argc >= argvlen)
336         {
337           argvlen = argc + 10;
338           argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
339         }
340
341       /* Add word to argv file after (optional) wildcard expansion. */
342       if (!winshell || !argc || !globify (word, argv, argc, argvlen))
343         {
344           debug_printf ("argv[%d] = '%s'", argc, word);
345           argv[argc++] = word;
346         }
347     }
348
349   argv[argc] = NULL;
350
351   debug_printf ("argc %d", argc);
352 }
353
354 /* sanity and sync check */
355 void __stdcall
356 check_sanity_and_sync (per_process *p)
357 {
358   /* Sanity check to make sure developers didn't change the per_process    */
359   /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
360   /* about changing it].                                                   */
361   if (sizeof (per_process) != SIZEOF_PER_PROCESS)
362     api_fatal ("per_process sanity check failed");
363
364   /* Make sure that the app and the dll are in sync. */
365
366   /* Complain if older than last incompatible change */
367   if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
368     api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
369                p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
370
371   /* magic_biscuit != 0 if using the old style version numbering scheme.  */
372   if (p->magic_biscuit != SIZEOF_PER_PROCESS)
373     api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
374                p->magic_biscuit, SIZEOF_PER_PROCESS);
375
376   /* Complain if incompatible API changes made */
377   if (p->api_major > cygwin_version.api_major)
378     api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
379                p->api_major, cygwin_version.api_major);
380
381   /* This is a kludge to work around a version of _cygwin_common_crt0
382      which overwrote the cxx_malloc field with the local DLL copy.
383      Hilarity ensues if the DLL is not loaded while the process
384      is forking. */
385   __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
386 }
387
388 child_info NO_COPY *child_proc_info = NULL;
389
390 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
391
392 void
393 child_info_fork::alloc_stack_hard_way (volatile char *b)
394 {
395   void *new_stack_pointer;
396   MEMORY_BASIC_INFORMATION m;
397   void *newbase;
398   int newlen;
399   bool guard;
400
401   if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
402     api_fatal ("fork: couldn't get stack info, %E");
403
404   LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
405
406   if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
407     {
408       newbase = curbot;
409       newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
410       guard = false;
411     }
412   else
413     {
414       newbase = (LPBYTE) stacktop - (128 * 1024);
415       newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
416       guard = true;
417     }
418
419   if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
420     api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
421                 stacktop, stackbottom);
422   new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
423   if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
424                      PAGE_EXECUTE_READWRITE))
425     api_fatal ("fork: can't commit memory for stack %p(%d), %E",
426                new_stack_pointer, stacksize);
427   if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
428     api_fatal ("fork: couldn't get new stack info, %E");
429
430   if (guard)
431     {
432       m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
433       if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
434                          CYGWIN_GUARD))
435         api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
436                    m.BaseAddress);
437     }
438   if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
439     api_fatal ("fork: couldn't get new stack info, %E");
440   stacktop = m.BaseAddress;
441   b[0] = '\0';
442 }
443
444 void *getstack (void *) __attribute__ ((noinline));
445 volatile char *
446 getstack (volatile char * volatile p)
447 {
448   *p ^= 1;
449   *p ^= 1;
450   return p - 4096;
451 }
452
453 /* extend the stack prior to fork longjmp */
454
455 void
456 child_info_fork::alloc_stack ()
457 {
458   volatile char * volatile esp;
459   __asm__ volatile ("movl %%esp,%0": "=r" (esp));
460   if (_tlsbase != stackbottom)
461     alloc_stack_hard_way (esp);
462   else
463     {
464       char *st = (char *) stacktop - 4096;
465       while (_tlstop >= st)
466         esp = getstack (esp);
467       stacksize = 0;
468     }
469 }
470
471 extern "C" void
472 break_here ()
473 {
474   static int NO_COPY sent_break;
475   if (!sent_break++)
476     DebugBreak ();
477   debug_printf ("break here");
478 }
479
480 static void
481 initial_env ()
482 {
483   if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
484     _cygwin_testing = 1;
485
486 #ifdef DEBUGGING
487   char buf[NT_MAX_PATH];
488   DWORD len;
489
490   if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
491     {
492       DWORD ms = atoi (buf);
493       console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
494       Sleep (ms);
495       if (!strace.active () && !dynamically_loaded)
496         strace.hello ();
497     }
498   if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
499     {
500       char buf1[NT_MAX_PATH];
501       len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
502       strlwr (buf1);
503       strlwr (buf);
504       char *p = strpbrk (buf, ":=");
505       if (!p)
506         p = (char *) "gdb.exe -nw";
507       else
508         *p++ = '\0';
509       if (strstr (buf1, buf))
510         {
511           error_start_init (p);
512           jit_debug = true;
513           try_to_debug ();
514           console_printf ("*** Sending Break.  gdb may issue spurious SIGTRAP message.\n");
515           break_here ();
516         }
517     }
518 #endif
519
520 }
521
522 child_info *
523 get_cygwin_startup_info ()
524 {
525   STARTUPINFO si;
526
527   GetStartupInfo (&si);
528   child_info *res = (child_info *) si.lpReserved2;
529
530   if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
531       || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
532     res = NULL;
533   else
534     {
535       if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
536         multiple_cygwin_problem ("proc intro", res->intro, 0);
537       else if (res->cygheap != (void *) &_cygheap_start)
538         multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
539                                  (DWORD) &_cygheap_start);
540
541       unsigned should_be_cb = 0;
542       switch (res->type)
543         {
544           case _PROC_FORK:
545             in_forkee = true;
546             should_be_cb = sizeof (child_info_fork);
547             /* fall through */;
548           case _PROC_SPAWN:
549           case _PROC_EXEC:
550             if (!should_be_cb)
551               should_be_cb = sizeof (child_info_spawn);
552             if (should_be_cb != res->cb)
553               multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
554             else if (sizeof (fhandler_union) != res->fhandler_union_cb)
555               multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
556             if (res->isstraced ())
557               {
558                 res->ready (false);
559                 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
560                   yield ();
561                 strace.hello ();
562               }
563             break;
564           default:
565             system_printf ("unknown exec type %d", res->type);
566             /* intentionally fall through */
567           case _PROC_WHOOPS:
568             res = NULL;
569             break;
570         }
571     }
572
573   return res;
574 }
575
576 #define dll_data_start &_data_start__
577 #define dll_data_end &_data_end__
578 #define dll_bss_start &_bss_start__
579 #define dll_bss_end &_bss_end__
580
581 void
582 child_info_fork::handle_fork ()
583 {
584   cygheap_fixup_in_child (false);
585   memory_init (false);
586   myself.thisproc (NULL);
587   myself->uid = cygheap->user.real_uid;
588   myself->gid = cygheap->user.real_gid;
589
590   child_copy (parent, false,
591               "dll data", dll_data_start, dll_data_end,
592               "dll bss", dll_bss_start, dll_bss_end,
593               "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
594               NULL);
595
596   /* Do the relocations here.  These will actually likely be overwritten by the
597      below child_copy but we do them here in case there is a read-only section
598      which does not get copied by fork. */
599   _pei386_runtime_relocator (user_data);
600
601   /* step 2 now that the dll has its heap filled in, we can fill in the
602      user's data and bss since user_data is now filled out. */
603   child_copy (parent, false,
604               "data", user_data->data_start, user_data->data_end,
605               "bss", user_data->bss_start, user_data->bss_end,
606               NULL);
607
608   if (fixup_mmaps_after_fork (parent))
609     api_fatal ("recreate_mmaps_after_fork_failed");
610 }
611
612 void
613 child_info_spawn::handle_spawn ()
614 {
615   extern void fixup_lockf_after_exec ();
616   HANDLE h;
617   cygheap_fixup_in_child (true);
618   memory_init (false);
619   if (!moreinfo->myself_pinfo ||
620       !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
621                         GetCurrentProcess (), &h, 0,
622                         FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
623     h = NULL;
624   myself.thisproc (h);
625   __argc = moreinfo->argc;
626   __argv = moreinfo->argv;
627   envp = moreinfo->envp;
628   envc = moreinfo->envc;
629   if (!dynamically_loaded)
630     cygheap->fdtab.fixup_after_exec ();
631   if (__stdin >= 0)
632     cygheap->fdtab.move_fd (__stdin, 0);
633   if (__stdout >= 0)
634     cygheap->fdtab.move_fd (__stdout, 1);
635   cygheap->user.groups.clear_supp ();
636
637   ready (true);
638
639   /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
640      handles might get confused. */
641   CloseHandle (child_proc_info->parent);
642   child_proc_info->parent = NULL;
643
644   signal_fixup_after_exec ();
645   if (moreinfo->old_title)
646     {
647       old_title = strcpy (title_buf, moreinfo->old_title);
648       cfree (moreinfo->old_title);
649     }
650   fixup_lockf_after_exec ();
651 }
652
653 #if 0
654 /* Setting the TS-aware flag in the application's PE header is sufficient.
655    Just keep this in as a reminder. */
656
657 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
658
659 static void
660 disable_dep ()
661 {
662   DWORD ppolicy;
663   BOOL perm;
664
665   if (dep_system_policy < 0)
666     {
667       dep_system_policy = GetSystemDEPPolicy ();
668       debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
669     }
670   if (dep_system_policy < OptIn)
671     return;
672   if (!GetProcessDEPPolicy (GetCurrentProcess (), &ppolicy, &perm))
673     {
674       debug_printf ("GetProcessDEPPolicy: %E");
675       return;
676     }
677   debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
678   if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
679     debug_printf ("SetProcessDEPPolicy: %E");
680 }
681 #endif
682
683 /* Retrieve and store system directory for later use.  Note that the 
684    directory is stored with a trailing backslash! */
685 static void
686 init_windows_system_directory ()
687 {
688   windows_system_directory_length =
689         GetSystemDirectoryW (windows_system_directory, MAX_PATH);
690   if (windows_system_directory_length == 0)
691     api_fatal ("can't find windows system directory");
692   windows_system_directory[windows_system_directory_length++] = L'\\';
693   windows_system_directory[windows_system_directory_length] = L'\0';
694 }
695
696 void __stdcall
697 dll_crt0_0 ()
698 {
699   init_windows_system_directory ();
700   init_global_security ();
701   initial_env ();
702
703   SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
704
705   lock_process::init ();
706   _impure_ptr = _GLOBAL_REENT;
707   _impure_ptr->_stdin = &_impure_ptr->__sf[0];
708   _impure_ptr->_stdout = &_impure_ptr->__sf[1];
709   _impure_ptr->_stderr = &_impure_ptr->__sf[2];
710   _impure_ptr->_current_locale = "C";
711   user_data->impure_ptr = _impure_ptr;
712   user_data->impure_ptr_ptr = &_impure_ptr;
713
714   DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
715                    GetCurrentProcess (), &hMainThread,
716                    0, false, DUPLICATE_SAME_ACCESS);
717
718   OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
719   set_cygwin_privileges (hProcToken);
720
721   device::init ();
722   do_global_ctors (&__CTOR_LIST__, 1);
723   cygthread::init ();
724
725   child_proc_info = get_cygwin_startup_info ();
726   if (!child_proc_info)
727     memory_init (true);
728   else
729     {
730       cygwin_user_h = child_proc_info->user_h;
731       switch (child_proc_info->type)
732         {
733           case _PROC_FORK:
734             fork_info->handle_fork ();
735             break;
736           case _PROC_SPAWN:
737           case _PROC_EXEC:
738             spawn_info->handle_spawn ();
739             break;
740         }
741     }
742
743   user_data->threadinterface->Init ();
744
745   _cygtls::init ();
746
747   /* Initialize events */
748   events_init ();
749   tty_list::init_session ();
750
751 #if 0
752   /* Setting the TS-aware flag in the application's PE header is sufficient.
753      Just keep this in as a reminder. */
754
755   /* The disable_dep function disables DEP for all Cygwin processes if
756      the process runs on a Windows Server 2008 with Terminal Services
757      installed.  This combination (TS+DEP) breaks *some* Cygwin
758      applications.  The Terminal Service specific DLL tsappcmp.dll
759      changes the page protection of some pages in the application's text
760      segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
761      apparent reason.  This occurs before any Cygwin or applicaton code
762      had a chance to run.  MS has no explanation for this so far, but is
763      rather busy trying to avoid giving support for this problem (as of
764      2008-11-11).
765
766      Unfortunately disabling DEP seems to have a not negligible
767      performance hit.  In the long run, either MS has to fix their
768      problem, or we have to find a better workaround, if any exists.
769      Idle idea: Adding EXECUTE protection to all text segment pages? */
770   if (wincap.ts_has_dep_problem ())
771     disable_dep ();
772 #endif
773
774   _main_tls = &_my_tls;
775
776   /* Initialize signal processing here, early, in the hopes that the creation
777      of a thread early in the process will cause more predictability in memory
778      layout for the main thread. */
779   if (!wincap.has_buggy_thread_startup () && !dynamically_loaded)
780     sigproc_init ();
781
782   debug_printf ("finished dll_crt0_0 initialization");
783 }
784
785 /* Take over from libc's crt0.o and start the application. Note the
786    various special cases when Cygwin DLL is being runtime loaded (as
787    opposed to being link-time loaded by Cygwin apps) from a non
788    cygwin app via LoadLibrary.  */
789 void
790 dll_crt0_1 (void *)
791 {
792   extern void initial_setlocale ();
793
794   if (wincap.has_buggy_thread_startup () || dynamically_loaded)
795     sigproc_init ();
796   check_sanity_and_sync (user_data);
797
798   /* Initialize malloc and then call user_shared_initialize since it relies
799      on a functioning malloc and it's possible that the user's program may
800      have overridden malloc.  We only know about that at this stage,
801      unfortunately. */
802   malloc_init ();
803   user_shared->initialize ();
804
805 #ifdef CGF
806   int i = 0;
807   const int n = 2 * 1024 * 1024;
808   while (i--)
809     small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
810 #endif
811
812   ProtectHandle (hMainThread);
813
814   cygheap->cwd.init ();
815
816   /* Initialize pthread mainthread when not forked and it is safe to call new,
817      otherwise it is reinitalized in fixup_after_fork */
818   if (!in_forkee)
819     {
820       pthread::init_mainthread ();
821       _pei386_runtime_relocator (user_data);
822     }
823
824 #ifdef DEBUGGING
825   strace.microseconds ();
826 #endif
827
828   create_signal_arrived (); /* FIXME: move into wait_sig? */
829
830   /* Initialize debug muto, if DLL is built with --enable-debugging.
831      Need to do this before any helper threads start. */
832   debug_init ();
833
834 #ifdef NEWVFORK
835   cygheap->fdtab.vfork_child_fixup ();
836   main_vfork = vfork_storage.create ();
837 #endif
838
839   cygbench ("pre-forkee");
840   if (in_forkee)
841     {
842       /* If we've played with the stack, stacksize != 0.  That means that
843          fork() was invoked from other than the main thread.  Make sure that
844          frame pointer is referencing the new stack so that the OS knows what
845          to do when it needs to increase the size of the stack.
846
847          NOTE: Don't do anything that involves the stack until you've completed
848          this step. */
849       if (fork_info->stacksize)
850         {
851           _tlsbase = (char *) fork_info->stackbottom;
852           _tlstop = (char *) fork_info->stacktop;
853         }
854
855       longjmp (fork_info->jmp, true);
856     }
857
858   __sinit (_impure_ptr);
859
860 #ifdef DEBUGGING
861   {
862   extern void fork_init ();
863   fork_init ();
864   }
865 #endif
866   pinfo_init (envp, envc);
867
868   if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
869     old_title = title_buf;
870
871   /* Allocate cygheap->fdtab */
872   dtable_init ();
873
874   uinfo_init ();        /* initialize user info */
875
876   /* Connect to tty. */
877   tty::init_session ();
878
879   /* Set internal locale to the environment settings. */
880   initial_setlocale ();
881
882   if (!__argc)
883     {
884       PWCHAR wline = GetCommandLineW ();
885       size_t size = sys_wcstombs (NULL, 0, wline);
886       char *line = (char *) alloca (size);
887       sys_wcstombs (line, size, wline);
888
889       /* Scan the command line and build argv.  Expand wildcards if not
890          called from another cygwin process. */
891       build_argv (line, __argv, __argc,
892                   NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
893
894       /* Convert argv[0] to posix rules if it's currently blatantly
895          win32 style. */
896       if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
897         {
898           char *new_argv0 = (char *) malloc (NT_MAX_PATH);
899           cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
900                             new_argv0, NT_MAX_PATH);
901           __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
902         }
903     }
904
905   __argc_safe = __argc;
906   if (user_data->premain[0])
907     for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
908       user_data->premain[i] (__argc, __argv, user_data);
909
910   /* Set up standard fds in file descriptor table. */
911   cygheap->fdtab.stdio_init ();
912
913   /* Set up __progname for getopt error call. */
914   if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
915     ++__progname;
916   else
917     __progname = __argv[0];
918   program_invocation_name = __argv[0];
919   program_invocation_short_name = __progname;
920   if (__progname)
921     {
922       char *cp = strchr (__progname, '\0') - 4;
923       if (cp > __progname && ascii_strcasematch (cp, ".exe"))
924         *cp = '\0';
925     }
926
927   /* Set new console title if appropriate. */
928
929   if (display_title && !dynamically_loaded)
930     {
931       char *cp = __progname;
932       if (strip_title_path)
933         for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
934           if (isdirsep (*ptr))
935             cp = ptr + 1;
936       set_console_title (cp);
937     }
938
939   (void) xdr_set_vprintf (&cygxdr_vwarnx);
940   cygwin_finished_initializing = true;
941   /* Call init of loaded dlls. */
942   dlls.init ();
943
944   /* Execute any specified "premain" functions */
945   if (user_data->premain[PREMAIN_LEN / 2])
946     for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
947       user_data->premain[i] (__argc, __argv, user_data);
948
949   set_errno (0);
950
951   if (dynamically_loaded)
952     return;
953
954   /* Disable case-insensitive globbing */
955   ignore_case_with_glob = false;
956
957   MALLOC_CHECK;
958   cygbench (__progname);
959
960   ld_preload ();
961   /* Per POSIX set the default application locale back to "C". */
962   _setlocale_r (_REENT, LC_CTYPE, "C");
963
964   if (user_data->main)
965     cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
966   __asm__ ("                            \n\
967         .global __cygwin_exit_return    \n\
968 __cygwin_exit_return:                   \n\
969 ");
970 }
971
972 extern "C" void __stdcall
973 _dll_crt0 ()
974 {
975   main_environ = user_data->envptr;
976   if (in_forkee)
977     {
978       fork_info->alloc_stack ();
979       _main_tls = &_my_tls;
980     }
981
982   _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
983 }
984
985 void
986 dll_crt0 (per_process *uptr)
987 {
988   /* Set the local copy of the pointer into the user space. */
989   if (!in_forkee && uptr && uptr != user_data)
990     {
991       memcpy (user_data, uptr, per_process_overwrite);
992       *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
993     }
994   _dll_crt0 ();
995 }
996
997 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
998    You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
999    calling this function, and that storage must not be overwritten until you
1000    unload cygwin1.dll, as it is used for _my_tls.  It is best to load
1001    cygwin1.dll before spawning any additional threads in your process.
1002
1003    See winsup/testsuite/cygload for an example of how to use cygwin1.dll
1004    from MSVC and non-cygwin MinGW applications.  */
1005 extern "C" void
1006 cygwin_dll_init ()
1007 {
1008   static char **envp;
1009   static int _fmode;
1010
1011   user_data->magic_biscuit = sizeof (per_process);
1012
1013   user_data->envptr = &envp;
1014   user_data->fmode_ptr = &_fmode;
1015
1016   _dll_crt0 ();
1017 }
1018
1019 extern "C" void
1020 __main (void)
1021 {
1022   /* Ordering is critical here.  DLL ctors have already been
1023      run as they were being loaded, so we should stack the
1024      queued call to DLL dtors now.  */
1025   atexit (dll_global_dtors);
1026   do_global_ctors (user_data->ctors, false);
1027   /* Now we have run global ctors, register their dtors.
1028
1029      At exit, global dtors will run first, so the app can still
1030      use shared library functions while terminating; then the
1031      DLLs will be destroyed; finally newlib will shut down stdio
1032      and terminate itself.  */
1033   atexit (do_global_dtors);
1034   sig_dispatch_pending (true);
1035 }
1036
1037 void __stdcall
1038 do_exit (int status)
1039 {
1040   syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1041
1042 #ifdef NEWVFORK
1043   vfork_save *vf = vfork_storage.val ();
1044   if (vf != NULL && vf->pid < 0)
1045     {
1046       exit_state = ES_NOT_EXITING;
1047       vf->restore_exit (status);
1048     }
1049 #endif
1050
1051   lock_process until_exit (true);
1052
1053   if (exit_state < ES_EVENTS_TERMINATE)
1054     {
1055       exit_state = ES_EVENTS_TERMINATE;
1056       events_terminate ();
1057     }
1058
1059   if (exit_state < ES_SIGNAL)
1060     {
1061       exit_state = ES_SIGNAL;
1062       signal (SIGCHLD, SIG_IGN);
1063       signal (SIGHUP, SIG_IGN);
1064       signal (SIGINT, SIG_IGN);
1065       signal (SIGQUIT, SIG_IGN);
1066     }
1067
1068   if (exit_state < ES_CLOSEALL)
1069     {
1070       exit_state = ES_CLOSEALL;
1071       close_all_files ();
1072     }
1073
1074   UINT n = (UINT) status;
1075   if (exit_state < ES_THREADTERM)
1076     {
1077       exit_state = ES_THREADTERM;
1078       cygthread::terminate ();
1079     }
1080
1081   myself->stopsig = 0;
1082
1083   if (exit_state < ES_HUP_PGRP)
1084     {
1085       exit_state = ES_HUP_PGRP;
1086       /* Kill orphaned children on group leader exit */
1087       if (myself->has_pgid_children && myself->pid == myself->pgid)
1088         {
1089           siginfo_t si = {0};
1090           si.si_signo = -SIGHUP;
1091           si.si_code = SI_KERNEL;
1092           sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1093                           myself->pid, myself->pgid);
1094           kill_pgrp (myself->pgid, si);
1095         }
1096     }
1097
1098   if (exit_state < ES_HUP_SID)
1099     {
1100       exit_state = ES_HUP_SID;
1101       /* Kill the foreground process group on session leader exit */
1102       if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1103         {
1104           tty *tp = cygwin_shared->tty[myself->ctty];
1105           sigproc_printf ("%d == sid %d, send SIGHUP to children",
1106                           myself->pid, myself->sid);
1107
1108         /* CGF FIXME: This can't be right. */
1109           if (tp->getsid () == myself->sid)
1110             tp->kill_pgrp (SIGHUP);
1111         }
1112
1113     }
1114
1115   if (exit_state < ES_TITLE)
1116     {
1117       exit_state = ES_TITLE;
1118       /* restore console title */
1119       if (old_title && display_title)
1120         set_console_title (old_title);
1121     }
1122
1123   if (exit_state < ES_TTY_TERMINATE)
1124     {
1125       exit_state = ES_TTY_TERMINATE;
1126       cygwin_shared->tty.terminate ();
1127     }
1128
1129   myself.exit (n);
1130 }
1131
1132 extern "C" int
1133 cygwin_atexit (void (*fn) (void))
1134 {
1135   int res;
1136   dll *d = dlls.find ((void *) _my_tls.retaddr ());
1137   res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1138   return res;
1139 }
1140
1141 extern "C" void
1142 cygwin_exit (int n)
1143 {
1144   exit_state = ES_EXIT_STARTING;
1145   exit (n);
1146 }
1147
1148 extern "C" void
1149 _exit (int n)
1150 {
1151   do_exit (((DWORD) n & 0xff) << 8);
1152 }
1153
1154 extern "C" void cygwin_stackdump ();
1155
1156 extern "C" void
1157 __api_fatal (const char *fmt, ...)
1158 {
1159   char buf[4096];
1160   va_list ap;
1161
1162   va_start (ap, fmt);
1163   int n = __small_sprintf (buf, "%P: *** fatal error - ");
1164   __small_vsprintf (buf + n, fmt, ap);
1165   va_end (ap);
1166   strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1167
1168 #ifdef DEBUGGING
1169   try_to_debug ();
1170 #endif
1171   cygwin_stackdump ();
1172   myself.exit (__api_fatal_exit_val);
1173 }
1174
1175 void
1176 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1177 {
1178   if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1179     {
1180       child_proc_info->type = _PROC_WHOOPS;
1181       return;
1182     }
1183
1184   if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1185     return;
1186
1187   if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1188     system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1189   else
1190     api_fatal ("%s mismatch detected - %p/%p.\n\
1191 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1192 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1193 and delete all but the most recent version.  The most recent version *should*\n\
1194 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1195 installed the cygwin distribution.  Rebooting is also suggested if you\n\
1196 are unable to find another cygwin DLL.",
1197                what, magic_version, version);
1198 }
1199
1200 #ifdef DEBUGGING
1201 void __stdcall
1202 cygbench (const char *s)
1203 {
1204   if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1205     small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1206 }
1207 #endif