OSDN Git Service

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