OSDN Git Service

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