OSDN Git Service

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