OSDN Git Service

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