OSDN Git Service

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