OSDN Git Service

* cygheap.cc (cygheap_init): Default locale.charset to "UTF-8".
[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   /* This is a kludge to work around a version of _cygwin_common_crt0
770      which overwrote the cxx_malloc field with the local DLL copy.
771      Hilarity ensues if the DLL is not loaded like while the process
772      is forking. */
773   __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
774
775   /* Initialize malloc and then call user_shared_initialize since it relies
776      on a functioning malloc and it's possible that the user's program may
777      have overridden malloc.  We only know about that at this stage,
778      unfortunately. */
779   malloc_init ();
780   user_shared_initialize ();
781
782 #ifdef CGF
783   int i = 0;
784   const int n = 2 * 1024 * 1024;
785   while (i--)
786     small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
787 #endif
788
789   ProtectHandle (hMainProc);
790   ProtectHandle (hMainThread);
791
792   cygheap->cwd.init ();
793
794   /* Initialize pthread mainthread when not forked and it is safe to call new,
795      otherwise it is reinitalized in fixup_after_fork */
796   if (!in_forkee)
797     pthread::init_mainthread ();
798
799 #ifdef DEBUGGING
800   strace.microseconds ();
801 #endif
802
803   create_signal_arrived (); /* FIXME: move into wait_sig? */
804
805   /* Initialize debug muto, if DLL is built with --enable-debugging.
806      Need to do this before any helper threads start. */
807   debug_init ();
808
809 #ifdef NEWVFORK
810   cygheap->fdtab.vfork_child_fixup ();
811   main_vfork = vfork_storage.create ();
812 #endif
813
814   cygbench ("pre-forkee");
815   if (in_forkee)
816     {
817       /* If we've played with the stack, stacksize != 0.  That means that
818          fork() was invoked from other than the main thread.  Make sure that
819          frame pointer is referencing the new stack so that the OS knows what
820          to do when it needs to increase the size of the stack.
821
822          NOTE: Don't do anything that involves the stack until you've completed
823          this step. */
824       if (fork_info->stacksize)
825         {
826           _tlsbase = (char *) fork_info->stackbottom;
827           _tlstop = (char *) fork_info->stacktop;
828           _my_tls.init_exception_handler (_cygtls::handle_exceptions);
829         }
830
831       longjmp (fork_info->jmp, true);
832     }
833
834 #ifdef DEBUGGING
835   {
836   extern void fork_init ();
837   fork_init ();
838   }
839 #endif
840   pinfo_init (envp, envc);
841
842   if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
843     old_title = title_buf;
844
845   /* Allocate cygheap->fdtab */
846   dtable_init ();
847
848   uinfo_init ();        /* initialize user info */
849
850   wait_for_sigthread ();
851   extern DWORD threadfunc_ix;
852   if (!threadfunc_ix)
853     system_printf ("internal error: couldn't determine location of thread function on stack.  Expect signal problems.");
854
855   /* Connect to tty. */
856   tty::init_session ();
857
858   if (!__argc)
859     {
860       PWCHAR wline = GetCommandLineW ();
861       size_t size = sys_wcstombs (NULL, 0, wline);
862       char *line = (char *) alloca (size);
863       sys_wcstombs (line, size, wline);
864
865       /* Scan the command line and build argv.  Expand wildcards if not
866          called from another cygwin process. */
867       build_argv (line, __argv, __argc,
868                   NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
869
870       /* Convert argv[0] to posix rules if it's currently blatantly
871          win32 style. */
872       if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
873         {
874           char *new_argv0 = (char *) malloc (NT_MAX_PATH);
875           cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
876                             new_argv0, NT_MAX_PATH);
877           __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
878         }
879     }
880
881   __argc_safe = __argc;
882   if (user_data->premain[0])
883     for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
884       user_data->premain[i] (__argc, __argv, user_data);
885
886   /* Set up standard fds in file descriptor table. */
887   cygheap->fdtab.stdio_init ();
888
889   /* Set up __progname for getopt error call. */
890   if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
891     ++__progname;
892   else
893     __progname = __argv[0];
894   if (__progname)
895     {
896       char *cp = strchr (__progname, '\0') - 4;
897       if (cp > __progname && ascii_strcasematch (cp, ".exe"))
898         *cp = '\0';
899     }
900
901   /* Set new console title if appropriate. */
902
903   if (display_title && !dynamically_loaded)
904     {
905       char *cp = __progname;
906       if (strip_title_path)
907         for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
908           if (isdirsep (*ptr))
909             cp = ptr + 1;
910       set_console_title (cp);
911     }
912
913   cygwin_finished_initializing = true;
914   /* Call init of loaded dlls. */
915   dlls.init ();
916
917   /* Execute any specified "premain" functions */
918   if (user_data->premain[PREMAIN_LEN / 2])
919     for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
920       user_data->premain[i] (__argc, __argv, user_data);
921
922   debug_printf ("user_data->main %p", user_data->main);
923
924   if (dynamically_loaded)
925     {
926       set_errno (0);
927       return;
928     }
929
930   /* Disable case-insensitive globbing */
931   ignore_case_with_glob = false;
932
933   set_errno (0);
934
935   MALLOC_CHECK;
936   cygbench (__progname);
937
938   /* Flush signals and ensure that signal thread is up and running. Can't
939      do this for noncygwin case since the signal thread is blocked due to
940      LoadLibrary serialization. */
941   ld_preload ();
942   /* Set internal locale to the environment settings. */
943   setlocale (LC_CTYPE, "");
944   /* Reset application locale to "C" per POSIX */
945   _setlocale_r (_REENT, LC_CTYPE, "C");
946   if (user_data->main)
947     cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
948   __asm__ ("                            \n\
949         .global __cygwin_exit_return    \n\
950 __cygwin_exit_return:                   \n\
951 ");
952 }
953
954 extern "C" void __stdcall
955 _dll_crt0 ()
956 {
957   main_environ = user_data->envptr;
958   if (in_forkee)
959     fork_info->alloc_stack ();
960   else
961     __sinit (_impure_ptr);
962
963   _main_tls = &_my_tls;
964   _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
965 }
966
967 void
968 dll_crt0 (per_process *uptr)
969 {
970   /* Set the local copy of the pointer into the user space. */
971   if (!in_forkee && uptr && uptr != user_data)
972     {
973       memcpy (user_data, uptr, per_process_overwrite);
974       *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
975     }
976   _dll_crt0 ();
977 }
978
979 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
980    You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
981    calling this function, and that storage must not be overwritten until you
982    unload cygwin1.dll, as it is used for _my_tls.  It is best to load
983    cygwin1.dll before spawning any additional threads in your process.
984
985    See winsup/testsuite/cygload for an example of how to use cygwin1.dll
986    from MSVC and non-cygwin MinGW applications.  */
987 extern "C" void
988 cygwin_dll_init ()
989 {
990   static char **envp;
991   static int _fmode;
992
993   user_data->magic_biscuit = sizeof (per_process);
994
995   user_data->envptr = &envp;
996   user_data->fmode_ptr = &_fmode;
997
998   _dll_crt0 ();
999 }
1000
1001 extern "C" void
1002 __main (void)
1003 {
1004   /* Ordering is critical here.  DLL ctors have already been
1005      run as they were being loaded, so we should stack the
1006      queued call to DLL dtors now.  */
1007   atexit (dll_global_dtors);
1008   do_global_ctors (user_data->ctors, false);
1009   /* Now we have run global ctors, register their dtors.  */
1010   atexit (do_global_dtors);
1011   /* At exit, global dtors will run first, so the app can still
1012      use shared library functions while terminating; then the
1013      DLLs will be destroyed; finally newlib will shut down stdio
1014      and terminate itself.  */
1015 }
1016
1017 void __stdcall
1018 do_exit (int status)
1019 {
1020   syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1021
1022 #ifdef NEWVFORK
1023   vfork_save *vf = vfork_storage.val ();
1024   if (vf != NULL && vf->pid < 0)
1025     {
1026       exit_state = ES_NOT_EXITING;
1027       vf->restore_exit (status);
1028     }
1029 #endif
1030
1031   lock_process until_exit (true);
1032
1033   if (exit_state < ES_EVENTS_TERMINATE)
1034     {
1035       exit_state = ES_EVENTS_TERMINATE;
1036       events_terminate ();
1037     }
1038
1039   UINT n = (UINT) status;
1040   if (exit_state < ES_THREADTERM)
1041     {
1042       exit_state = ES_THREADTERM;
1043       cygthread::terminate ();
1044     }
1045
1046   if (exit_state < ES_SIGNAL)
1047     {
1048       exit_state = ES_SIGNAL;
1049       signal (SIGCHLD, SIG_IGN);
1050       signal (SIGHUP, SIG_IGN);
1051       signal (SIGINT, SIG_IGN);
1052       signal (SIGQUIT, SIG_IGN);
1053     }
1054
1055   if (exit_state < ES_CLOSEALL)
1056     {
1057       exit_state = ES_CLOSEALL;
1058       close_all_files ();
1059     }
1060
1061   myself->stopsig = 0;
1062
1063   if (exit_state < ES_HUP_PGRP)
1064     {
1065       exit_state = ES_HUP_PGRP;
1066       /* Kill orphaned children on group leader exit */
1067       if (myself->has_pgid_children && myself->pid == myself->pgid)
1068         {
1069           siginfo_t si = {0};
1070           si.si_signo = -SIGHUP;
1071           si.si_code = SI_KERNEL;
1072           sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1073                           myself->pid, myself->pgid);
1074           kill_pgrp (myself->pgid, si);
1075         }
1076     }
1077
1078   if (exit_state < ES_HUP_SID)
1079     {
1080       exit_state = ES_HUP_SID;
1081       /* Kill the foreground process group on session leader exit */
1082       if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1083         {
1084           tty *tp = cygwin_shared->tty[myself->ctty];
1085           sigproc_printf ("%d == sid %d, send SIGHUP to children",
1086                           myself->pid, myself->sid);
1087
1088         /* CGF FIXME: This can't be right. */
1089           if (tp->getsid () == myself->sid)
1090             tp->kill_pgrp (SIGHUP);
1091         }
1092
1093     }
1094
1095   if (exit_state < ES_TITLE)
1096     {
1097       exit_state = ES_TITLE;
1098       /* restore console title */
1099       if (old_title && display_title)
1100         set_console_title (old_title);
1101     }
1102
1103   if (exit_state < ES_TTY_TERMINATE)
1104     {
1105       exit_state = ES_TTY_TERMINATE;
1106       cygwin_shared->tty.terminate ();
1107     }
1108
1109   myself.exit (n);
1110 }
1111
1112 static NO_COPY muto atexit_lock;
1113
1114 extern "C" int
1115 cygwin_atexit (void (*function)(void))
1116 {
1117   int res;
1118   atexit_lock.init ("atexit_lock");
1119   atexit_lock.acquire ();
1120   res = atexit (function);
1121   atexit_lock.release ();
1122   return res;
1123 }
1124
1125 extern "C" void
1126 cygwin_exit (int n)
1127 {
1128   if (atexit_lock)
1129     atexit_lock.acquire ();
1130   exit (n);
1131 }
1132
1133 extern "C" void
1134 _exit (int n)
1135 {
1136   do_exit (((DWORD) n & 0xff) << 8);
1137 }
1138
1139 extern "C" void
1140 __api_fatal (const char *fmt, ...)
1141 {
1142   char buf[4096];
1143   va_list ap;
1144
1145   va_start (ap, fmt);
1146   int n = __small_sprintf (buf, "%P: *** fatal error - ");
1147   __small_vsprintf (buf + n, fmt, ap);
1148   va_end (ap);
1149   strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1150
1151 #ifdef DEBUGGING
1152   try_to_debug ();
1153 #endif
1154   myself.exit (__api_fatal_exit_val);
1155 }
1156
1157 void
1158 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1159 {
1160   if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1161     {
1162       child_proc_info->type = _PROC_WHOOPS;
1163       return;
1164     }
1165
1166   if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1167     return;
1168
1169   if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1170     system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1171   else
1172     api_fatal ("%s mismatch detected - %p/%p.\n\
1173 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1174 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1175 and delete all but the most recent version.  The most recent version *should*\n\
1176 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1177 installed the cygwin distribution.  Rebooting is also suggested if you\n\
1178 are unable to find another cygwin DLL.",
1179                what, magic_version, version);
1180 }
1181
1182 #ifdef DEBUGGING
1183 void __stdcall
1184 cygbench (const char *s)
1185 {
1186   if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1187     small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1188 }
1189 #endif