OSDN Git Service

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