OSDN Git Service

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