OSDN Git Service

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