OSDN Git Service

* globals.cc (enum exit_states::ES_GLOBAL_DTORS): Delete.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / dcrt0.cc
1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4    2007, 2008, 2009
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
380 child_info NO_COPY *child_proc_info = NULL;
381
382 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
383
384 void
385 child_info_fork::alloc_stack_hard_way (volatile char *b)
386 {
387   void *new_stack_pointer;
388   MEMORY_BASIC_INFORMATION m;
389   void *newbase;
390   int newlen;
391   bool guard;
392
393   if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
394     api_fatal ("fork: couldn't get stack info, %E");
395
396   LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
397
398   if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
399     {
400       newbase = curbot;
401       newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
402       guard = false;
403     }
404   else
405     {
406       newbase = (LPBYTE) stacktop - (128 * 1024);
407       newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
408       guard = true;
409     }
410
411   if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
412     api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
413                 stacktop, stackbottom);
414   new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
415   if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
416                      PAGE_EXECUTE_READWRITE))
417     api_fatal ("fork: can't commit memory for stack %p(%d), %E",
418                new_stack_pointer, stacksize);
419   if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
420     api_fatal ("fork: couldn't get new stack info, %E");
421
422   if (guard)
423     {
424       m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
425       if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
426                          CYGWIN_GUARD))
427         api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
428                    m.BaseAddress);
429     }
430   if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
431     api_fatal ("fork: couldn't get new stack info, %E");
432   stacktop = m.BaseAddress;
433   b[0] = '\0';
434 }
435
436 void *getstack (void *) __attribute__ ((noinline));
437 volatile char *
438 getstack (volatile char * volatile p)
439 {
440   *p ^= 1;
441   *p ^= 1;
442   return p - 4096;
443 }
444
445 /* extend the stack prior to fork longjmp */
446
447 void
448 child_info_fork::alloc_stack ()
449 {
450   volatile char * volatile esp;
451   __asm__ volatile ("movl %%esp,%0": "=r" (esp));
452   if (_tlsbase != stackbottom)
453     alloc_stack_hard_way (esp);
454   else
455     {
456       char *st = (char *) stacktop - 4096;
457       while (_tlstop >= st)
458         esp = getstack (esp);
459       stacksize = 0;
460     }
461 }
462
463 extern "C" void
464 break_here ()
465 {
466   static int NO_COPY sent_break;
467   if (!sent_break++)
468     DebugBreak ();
469   debug_printf ("break here");
470 }
471
472 static void
473 initial_env ()
474 {
475   if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
476     _cygwin_testing = 1;
477
478 #ifdef DEBUGGING
479   char buf[NT_MAX_PATH];
480   DWORD len;
481
482   if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
483     {
484       DWORD ms = atoi (buf);
485       console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
486       Sleep (ms);
487       if (!strace.active () && !dynamically_loaded)
488         strace.hello ();
489     }
490   if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
491     {
492       char buf1[NT_MAX_PATH];
493       len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
494       strlwr (buf1);
495       strlwr (buf);
496       char *p = strpbrk (buf, ":=");
497       if (!p)
498         p = (char *) "gdb.exe -nw";
499       else
500         *p++ = '\0';
501       if (strstr (buf1, buf))
502         {
503           error_start_init (p);
504           jit_debug = true;
505           try_to_debug ();
506           console_printf ("*** Sending Break.  gdb may issue spurious SIGTRAP message.\n");
507           break_here ();
508         }
509     }
510 #endif
511
512 }
513
514 child_info *
515 get_cygwin_startup_info ()
516 {
517   STARTUPINFO si;
518
519   GetStartupInfo (&si);
520   child_info *res = (child_info *) si.lpReserved2;
521
522   if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
523       || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
524     res = NULL;
525   else
526     {
527       if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
528         multiple_cygwin_problem ("proc intro", res->intro, 0);
529       else if (res->cygheap != (void *) &_cygheap_start)
530         multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
531                                  (DWORD) &_cygheap_start);
532
533       unsigned should_be_cb = 0;
534       switch (res->type)
535         {
536           case _PROC_FORK:
537             in_forkee = true;
538             should_be_cb = sizeof (child_info_fork);
539             /* fall through */;
540           case _PROC_SPAWN:
541           case _PROC_EXEC:
542             if (!should_be_cb)
543               should_be_cb = sizeof (child_info_spawn);
544             if (should_be_cb != res->cb)
545               multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
546             else if (sizeof (fhandler_union) != res->fhandler_union_cb)
547               multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
548             if (res->isstraced ())
549               {
550                 res->ready (false);
551                 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
552                   low_priority_sleep (0);
553                 strace.hello ();
554               }
555             break;
556           default:
557             system_printf ("unknown exec type %d", res->type);
558             /* intentionally fall through */
559           case _PROC_WHOOPS:
560             res = NULL;
561             break;
562         }
563     }
564
565   return res;
566 }
567
568 #define dll_data_start &_data_start__
569 #define dll_data_end &_data_end__
570 #define dll_bss_start &_bss_start__
571 #define dll_bss_end &_bss_end__
572
573 void
574 child_info_fork::handle_fork ()
575 {
576   cygheap_fixup_in_child (false);
577   memory_init (false);
578   myself.thisproc (NULL);
579   myself->uid = cygheap->user.real_uid;
580   myself->gid = cygheap->user.real_gid;
581
582   child_copy (parent, false,
583               "dll data", dll_data_start, dll_data_end,
584               "dll bss", dll_bss_start, dll_bss_end,
585               "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
586               NULL);
587   /* step 2 now that the dll has its heap filled in, we can fill in the
588      user's data and bss since user_data is now filled out. */
589   child_copy (parent, false,
590               "data", user_data->data_start, user_data->data_end,
591               "bss", user_data->bss_start, user_data->bss_end,
592               NULL);
593
594   if (fixup_mmaps_after_fork (parent))
595     api_fatal ("recreate_mmaps_after_fork_failed");
596 }
597
598 void
599 child_info_spawn::handle_spawn ()
600 {
601   extern void fixup_lockf_after_exec ();
602   HANDLE h;
603   cygheap_fixup_in_child (true);
604   memory_init (false);
605   if (!moreinfo->myself_pinfo ||
606       !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
607                         FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
608     h = NULL;
609   myself.thisproc (h);
610   __argc = moreinfo->argc;
611   __argv = moreinfo->argv;
612   envp = moreinfo->envp;
613   envc = moreinfo->envc;
614   if (!dynamically_loaded)
615     cygheap->fdtab.fixup_after_exec ();
616   if (__stdin >= 0)
617     cygheap->fdtab.move_fd (__stdin, 0);
618   if (__stdout >= 0)
619     cygheap->fdtab.move_fd (__stdout, 1);
620   cygheap->user.groups.clear_supp ();
621
622   ready (true);
623
624   /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
625      handles might get confused. */
626   CloseHandle (child_proc_info->parent);
627   child_proc_info->parent = NULL;
628
629   signal_fixup_after_exec ();
630   if (moreinfo->old_title)
631     {
632       old_title = strcpy (title_buf, moreinfo->old_title);
633       cfree (moreinfo->old_title);
634     }
635   fixup_lockf_after_exec ();
636 }
637
638 #if 0
639 /* Setting the TS-aware flag in the application's PE header is sufficient.
640    Just keep this in as a reminder. */
641
642 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
643
644 static void
645 disable_dep ()
646 {
647   DWORD ppolicy;
648   BOOL perm;
649
650   if (dep_system_policy < 0)
651     {
652       dep_system_policy = GetSystemDEPPolicy ();
653       debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
654     }
655   if (dep_system_policy < OptIn)
656     return;
657   if (!GetProcessDEPPolicy (hMainProc, &ppolicy, &perm))
658     {
659       debug_printf ("GetProcessDEPPolicy: %E");
660       return;
661     }
662   debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
663   if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
664     debug_printf ("SetProcessDEPPolicy: %E");
665 }
666 #endif
667
668 void __stdcall
669 dll_crt0_0 ()
670 {
671   init_global_security ();
672   initial_env ();
673
674   SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
675
676   /* Initialize signal processing here, early, in the hopes that the creation
677      of a thread early in the process will cause more predictability in memory
678      layout for the main thread. */
679   if (!dynamically_loaded)
680     sigproc_init ();
681
682   lock_process::init ();
683   _impure_ptr = _GLOBAL_REENT;
684   _impure_ptr->_stdin = &_impure_ptr->__sf[0];
685   _impure_ptr->_stdout = &_impure_ptr->__sf[1];
686   _impure_ptr->_stderr = &_impure_ptr->__sf[2];
687   _impure_ptr->_current_locale = "C";
688   user_data->impure_ptr = _impure_ptr;
689   user_data->impure_ptr_ptr = &_impure_ptr;
690
691   if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
692                        GetCurrentProcess (), &hMainProc, 0, FALSE,
693                         DUPLICATE_SAME_ACCESS))
694     hMainProc = GetCurrentProcess ();
695
696   DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
697                    &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
698
699   OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
700   set_cygwin_privileges (hProcToken);
701
702   device::init ();
703   do_global_ctors (&__CTOR_LIST__, 1);
704   cygthread::init ();
705
706   child_proc_info = get_cygwin_startup_info ();
707   if (!child_proc_info)
708     memory_init (true);
709   else
710     {
711       cygwin_user_h = child_proc_info->user_h;
712       switch (child_proc_info->type)
713         {
714           case _PROC_FORK:
715             fork_info->handle_fork ();
716             break;
717           case _PROC_SPAWN:
718           case _PROC_EXEC:
719             spawn_info->handle_spawn ();
720             break;
721         }
722     }
723
724   user_data->threadinterface->Init ();
725
726   _cygtls::init ();
727
728   /* Initialize events */
729   events_init ();
730   tty_list::init_session ();
731
732 #if 0
733   /* Setting the TS-aware flag in the application's PE header is sufficient.
734      Just keep this in as a reminder. */
735
736   /* The disable_dep function disables DEP for all Cygwin processes if
737      the process runs on a Windows Server 2008 with Terminal Services
738      installed.  This combination (TS+DEP) breaks *some* Cygwin
739      applications.  The Terminal Service specific DLL tsappcmp.dll
740      changes the page protection of some pages in the application's text
741      segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
742      apparent reason.  This occurs before any Cygwin or applicaton code
743      had a chance to run.  MS has no explanation for this so far, but is
744      rather busy trying to avoid giving support for this problem (as of
745      2008-11-11).
746
747      Unfortunately disabling DEP seems to have a not negligible
748      performance hit.  In the long run, either MS has to fix their
749      problem, or we have to find a better workaround, if any exists.
750      Idle idea: Adding EXECUTE protection to all text segment pages? */
751   if (wincap.ts_has_dep_problem ())
752     disable_dep ();
753 #endif
754
755   debug_printf ("finished dll_crt0_0 initialization");
756 }
757
758 /* Take over from libc's crt0.o and start the application. Note the
759    various special cases when Cygwin DLL is being runtime loaded (as
760    opposed to being link-time loaded by Cygwin apps) from a non
761    cygwin app via LoadLibrary.  */
762 void
763 dll_crt0_1 (void *)
764 {
765   if (dynamically_loaded)
766     sigproc_init ();
767   check_sanity_and_sync (user_data);
768
769   /* Initialize malloc and then call user_shared_initialize since it relies
770      on a functioning malloc and it's possible that the user's program may
771      have overridden malloc.  We only know about that at this stage,
772      unfortunately. */
773   malloc_init ();
774   user_shared_initialize ();
775
776 #ifdef CGF
777   int i = 0;
778   const int n = 2 * 1024 * 1024;
779   while (i--)
780     small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
781 #endif
782
783   ProtectHandle (hMainProc);
784   ProtectHandle (hMainThread);
785
786   cygheap->cwd.init ();
787
788   /* Initialize pthread mainthread when not forked and it is safe to call new,
789      otherwise it is reinitalized in fixup_after_fork */
790   if (!in_forkee)
791     pthread::init_mainthread ();
792
793 #ifdef DEBUGGING
794   strace.microseconds ();
795 #endif
796
797   create_signal_arrived (); /* FIXME: move into wait_sig? */
798
799   /* Initialize debug muto, if DLL is built with --enable-debugging.
800      Need to do this before any helper threads start. */
801   debug_init ();
802
803 #ifdef NEWVFORK
804   cygheap->fdtab.vfork_child_fixup ();
805   main_vfork = vfork_storage.create ();
806 #endif
807
808   cygbench ("pre-forkee");
809   if (in_forkee)
810     {
811       /* If we've played with the stack, stacksize != 0.  That means that
812          fork() was invoked from other than the main thread.  Make sure that
813          frame pointer is referencing the new stack so that the OS knows what
814          to do when it needs to increase the size of the stack.
815
816          NOTE: Don't do anything that involves the stack until you've completed
817          this step. */
818       if (fork_info->stacksize)
819         {
820           _tlsbase = (char *) fork_info->stackbottom;
821           _tlstop = (char *) fork_info->stacktop;
822           _my_tls.init_exception_handler (_cygtls::handle_exceptions);
823         }
824
825       longjmp (fork_info->jmp, true);
826     }
827
828 #ifdef DEBUGGING
829   {
830   extern void fork_init ();
831   fork_init ();
832   }
833 #endif
834   pinfo_init (envp, envc);
835
836   if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
837     old_title = title_buf;
838
839   /* Allocate cygheap->fdtab */
840   dtable_init ();
841
842   uinfo_init ();        /* initialize user info */
843
844   wait_for_sigthread ();
845   extern DWORD threadfunc_ix;
846   if (!threadfunc_ix)
847     system_printf ("internal error: couldn't determine location of thread function on stack.  Expect signal problems.");
848
849   /* Connect to tty. */
850   tty::init_session ();
851
852   if (!__argc)
853     {
854       PWCHAR wline = GetCommandLineW ();
855       size_t size = sys_wcstombs (NULL, 0, wline);
856       char *line = (char *) alloca (size);
857       sys_wcstombs (line, size, wline);
858
859       /* Scan the command line and build argv.  Expand wildcards if not
860          called from another cygwin process. */
861       build_argv (line, __argv, __argc,
862                   NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
863
864       /* Convert argv[0] to posix rules if it's currently blatantly
865          win32 style. */
866       if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
867         {
868           char *new_argv0 = (char *) malloc (NT_MAX_PATH);
869           cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
870                             new_argv0, NT_MAX_PATH);
871           __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
872         }
873     }
874
875   __argc_safe = __argc;
876   if (user_data->premain[0])
877     for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
878       user_data->premain[i] (__argc, __argv, user_data);
879
880   /* Set up standard fds in file descriptor table. */
881   cygheap->fdtab.stdio_init ();
882
883   /* Set up __progname for getopt error call. */
884   if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
885     ++__progname;
886   else
887     __progname = __argv[0];
888   if (__progname)
889     {
890       char *cp = strchr (__progname, '\0') - 4;
891       if (cp > __progname && ascii_strcasematch (cp, ".exe"))
892         *cp = '\0';
893     }
894
895   /* Set new console title if appropriate. */
896
897   if (display_title && !dynamically_loaded)
898     {
899       char *cp = __progname;
900       if (strip_title_path)
901         for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
902           if (isdirsep (*ptr))
903             cp = ptr + 1;
904       set_console_title (cp);
905     }
906
907   cygwin_finished_initializing = true;
908   /* Call init of loaded dlls. */
909   dlls.init ();
910
911   /* Execute any specified "premain" functions */
912   if (user_data->premain[PREMAIN_LEN / 2])
913     for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
914       user_data->premain[i] (__argc, __argv, user_data);
915
916   debug_printf ("user_data->main %p", user_data->main);
917
918   if (dynamically_loaded)
919     {
920       set_errno (0);
921       return;
922     }
923
924   /* Disable case-insensitive globbing */
925   ignore_case_with_glob = false;
926
927   set_errno (0);
928
929   MALLOC_CHECK;
930   cygbench (__progname);
931
932   /* Flush signals and ensure that signal thread is up and running. Can't
933      do this for noncygwin case since the signal thread is blocked due to
934      LoadLibrary serialization. */
935   ld_preload ();
936   /* Reset current application locale to "C" per POSIX */
937   _setlocale_r (_REENT, LC_CTYPE, "C");
938   if (user_data->main)
939     cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
940   __asm__ ("                            \n\
941         .global __cygwin_exit_return    \n\
942 __cygwin_exit_return:                   \n\
943 ");
944 }
945
946 extern "C" void __stdcall
947 _dll_crt0 ()
948 {
949   main_environ = user_data->envptr;
950   if (in_forkee)
951     fork_info->alloc_stack ();
952   else
953     __sinit (_impure_ptr);
954
955   _main_tls = &_my_tls;
956   _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
957 }
958
959 void
960 dll_crt0 (per_process *uptr)
961 {
962   /* Set the local copy of the pointer into the user space. */
963   if (!in_forkee && uptr && uptr != user_data)
964     {
965       memcpy (user_data, uptr, per_process_overwrite);
966       *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
967     }
968   _dll_crt0 ();
969 }
970
971 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
972    You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
973    calling this function, and that storage must not be overwritten until you
974    unload cygwin1.dll, as it is used for _my_tls.  It is best to load
975    cygwin1.dll before spawning any additional threads in your process.
976
977    See winsup/testsuite/cygload for an example of how to use cygwin1.dll
978    from MSVC and non-cygwin MinGW applications.  */
979 extern "C" void
980 cygwin_dll_init ()
981 {
982   static char **envp;
983   static int _fmode;
984
985   user_data->magic_biscuit = sizeof (per_process);
986
987   user_data->envptr = &envp;
988   user_data->fmode_ptr = &_fmode;
989
990   _dll_crt0 ();
991 }
992
993 extern "C" void
994 __main (void)
995 {
996   /* Ordering is critical here.  DLL ctors have already been
997      run as they were being loaded, so we should stack the 
998      queued call to DLL dtors now.  */
999   atexit (dll_global_dtors);
1000   do_global_ctors (user_data->ctors, false);
1001   /* Now we have run global ctors, register their dtors.  */
1002   atexit (do_global_dtors);
1003   /* At exit, global dtors will run first, so the app can still
1004      use shared library functions while terminating; then the
1005      DLLs will be destroyed; finally newlib will shut down stdio
1006      and terminate itself.  */
1007 }
1008
1009 void __stdcall
1010 do_exit (int status)
1011 {
1012   syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1013
1014 #ifdef NEWVFORK
1015   vfork_save *vf = vfork_storage.val ();
1016   if (vf != NULL && vf->pid < 0)
1017     {
1018       exit_state = ES_NOT_EXITING;
1019       vf->restore_exit (status);
1020     }
1021 #endif
1022
1023   lock_process until_exit (true);
1024
1025   if (exit_state < ES_EVENTS_TERMINATE)
1026     {
1027       exit_state = ES_EVENTS_TERMINATE;
1028       events_terminate ();
1029     }
1030
1031   UINT n = (UINT) status;
1032   if (exit_state < ES_THREADTERM)
1033     {
1034       exit_state = ES_THREADTERM;
1035       cygthread::terminate ();
1036     }
1037
1038   if (exit_state < ES_SIGNAL)
1039     {
1040       exit_state = ES_SIGNAL;
1041       signal (SIGCHLD, SIG_IGN);
1042       signal (SIGHUP, SIG_IGN);
1043       signal (SIGINT, SIG_IGN);
1044       signal (SIGQUIT, SIG_IGN);
1045     }
1046
1047   if (exit_state < ES_CLOSEALL)
1048     {
1049       exit_state = ES_CLOSEALL;
1050       close_all_files ();
1051     }
1052
1053   myself->stopsig = 0;
1054
1055   if (exit_state < ES_HUP_PGRP)
1056     {
1057       exit_state = ES_HUP_PGRP;
1058       /* Kill orphaned children on group leader exit */
1059       if (myself->has_pgid_children && myself->pid == myself->pgid)
1060         {
1061           siginfo_t si = {0};
1062           si.si_signo = -SIGHUP;
1063           si.si_code = SI_KERNEL;
1064           sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1065                           myself->pid, myself->pgid);
1066           kill_pgrp (myself->pgid, si);
1067         }
1068     }
1069
1070   if (exit_state < ES_HUP_SID)
1071     {
1072       exit_state = ES_HUP_SID;
1073       /* Kill the foreground process group on session leader exit */
1074       if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1075         {
1076           tty *tp = cygwin_shared->tty[myself->ctty];
1077           sigproc_printf ("%d == sid %d, send SIGHUP to children",
1078                           myself->pid, myself->sid);
1079
1080         /* CGF FIXME: This can't be right. */
1081           if (tp->getsid () == myself->sid)
1082             tp->kill_pgrp (SIGHUP);
1083         }
1084
1085     }
1086
1087   if (exit_state < ES_TITLE)
1088     {
1089       exit_state = ES_TITLE;
1090       /* restore console title */
1091       if (old_title && display_title)
1092         set_console_title (old_title);
1093     }
1094
1095   if (exit_state < ES_TTY_TERMINATE)
1096     {
1097       exit_state = ES_TTY_TERMINATE;
1098       cygwin_shared->tty.terminate ();
1099     }
1100
1101   myself.exit (n);
1102 }
1103
1104 static NO_COPY muto atexit_lock;
1105
1106 extern "C" int
1107 cygwin_atexit (void (*function)(void))
1108 {
1109   int res;
1110   atexit_lock.init ("atexit_lock");
1111   atexit_lock.acquire ();
1112   res = atexit (function);
1113   atexit_lock.release ();
1114   return res;
1115 }
1116
1117 extern "C" void
1118 cygwin_exit (int n)
1119 {
1120   if (atexit_lock)
1121     atexit_lock.acquire ();
1122   exit (n);
1123 }
1124
1125 extern "C" void
1126 _exit (int n)
1127 {
1128   do_exit (((DWORD) n & 0xff) << 8);
1129 }
1130
1131 extern "C" void
1132 __api_fatal (const char *fmt, ...)
1133 {
1134   char buf[4096];
1135   va_list ap;
1136
1137   va_start (ap, fmt);
1138   int n = __small_sprintf (buf, "%P: *** fatal error - ");
1139   __small_vsprintf (buf + n, fmt, ap);
1140   va_end (ap);
1141   strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1142
1143 #ifdef DEBUGGING
1144   try_to_debug ();
1145 #endif
1146   myself.exit (__api_fatal_exit_val);
1147 }
1148
1149 void
1150 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1151 {
1152   if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1153     {
1154       child_proc_info->type = _PROC_WHOOPS;
1155       return;
1156     }
1157
1158   if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1159     return;
1160
1161   if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1162     system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1163   else
1164     api_fatal ("%s mismatch detected - %p/%p.\n\
1165 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1166 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1167 and delete all but the most recent version.  The most recent version *should*\n\
1168 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1169 installed the cygwin distribution.  Rebooting is also suggested if you\n\
1170 are unable to find another cygwin DLL.",
1171                what, magic_version, version);
1172 }
1173
1174 #ifdef DEBUGGING
1175 void __stdcall
1176 cygbench (const char *s)
1177 {
1178   if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1179     small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1180 }
1181 #endif