OSDN Git Service

47cd8b1b9aafed682a89f24a71aeb64637186c93
[pf3gnuchains/sourceware.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 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include "winsup.h"
12 #include <unistd.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include "glob.h"
16 #include "exceptions.h"
17 #include <ctype.h>
18 #include <limits.h>
19 #include <wingdi.h>
20 #include <winuser.h>
21 #include "sigproc.h"
22 #include "pinfo.h"
23 #include "cygerrno.h"
24 #define NEED_VFORK
25 #include "perprocess.h"
26 #include "security.h"
27 #include "path.h"
28 #include "fhandler.h"
29 #include "dtable.h"
30 #include "cygheap.h"
31 #include "child_info_magic.h"
32 #include "perthread.h"
33 #include "shared_info.h"
34 #include "cygwin_version.h"
35 #include "dll_init.h"
36 #include "cygthread.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 HANDLE NO_COPY hMainProc = (HANDLE) -1;
45 HANDLE NO_COPY hMainThread;
46
47 #ifdef NEWVFORK
48 per_thread_vfork NO_COPY vfork_storage;
49 #endif
50
51 per_thread NO_COPY *threadstuff[] = {
52 #ifdef NEWVFORK
53                                      &vfork_storage,
54 #endif
55                                      NULL};
56
57 bool display_title;
58 bool strip_title_path;
59 bool allow_glob = true;
60 codepage_type current_codepage = ansi_cp;
61
62 int __argc_safe;
63 int _declspec(dllexport) __argc;
64 char _declspec(dllexport) **__argv;
65 #ifdef NEWVFORK
66 vfork_save NO_COPY *main_vfork;
67 #endif
68
69 static int NO_COPY envc;
70 char NO_COPY **envp;
71
72 extern "C" void __sinit (_reent *);
73
74 _cygtls NO_COPY *_main_tls;
75
76 bool NO_COPY cygwin_finished_initializing;
77
78 /* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
79    This is subtracted from the signal number prior to shifting the bit.
80    In older versions of cygwin, the signal was used as-is to shift the
81    bit for masking.  So, we'll temporarily detect this and set it to zero
82    for programs that are linked using older cygwins.  This is just a stopgap
83    measure to allow an orderly transfer to the new, correct sigmask method. */
84 unsigned NO_COPY int signal_shift_subtract = 1;
85
86 ResourceLocks _reslock NO_COPY;
87 MTinterface _mtinterf;
88
89 bool NO_COPY _cygwin_testing;
90
91 char NO_COPY almost_null[1];
92
93 extern "C"
94 {
95   /* This is an exported copy of environ which can be used by DLLs
96      which use cygwin.dll.  */
97   char **__cygwin_environ;
98   char ***main_environ;
99   /* __progname used in getopt error message */
100   char *__progname;
101   struct per_process __cygwin_user_data =
102   {/* initial_sp */ 0, /* magic_biscuit */ 0,
103    /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
104    /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
105    /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
106    /* malloc */ malloc, /* free */ free,
107    /* realloc */ realloc,
108    /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
109    /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
110    /* bss_start */ NULL, /* bss_end */ NULL,
111    /* calloc */ calloc,
112    /* premain */ {NULL, NULL, NULL, NULL},
113    /* run_ctors_p */ 0,
114    /* unused */ {0, 0, 0, 0, 0, 0, 0},
115    /* forkee */ 0,
116    /* hmodule */ NULL,
117    /* api_major */ CYGWIN_VERSION_API_MAJOR,
118    /* api_minor */ CYGWIN_VERSION_API_MINOR,
119    /* unused2 */ {0, 0, 0, 0, 0},
120    /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
121    /* impure_ptr */ _GLOBAL_REENT,
122   };
123   bool ignore_case_with_glob;
124   int __declspec (dllexport) _check_for_executable = true;
125 #ifdef DEBUGGING
126   int pinger;
127 #endif
128 };
129
130 char *old_title;
131 char title_buf[TITLESIZE + 1];
132
133 static void
134 do_global_dtors (void)
135 {
136   if (user_data->dtors)
137     {
138       void (**pfunc)() = user_data->dtors;
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 && user_data->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     {
429       api_fatal ("per_process sanity check failed");
430     }
431
432   /* Make sure that the app and the dll are in sync. */
433
434   /* Complain if older than last incompatible change */
435   if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
436     api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
437                p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
438
439   /* magic_biscuit != 0 if using the old style version numbering scheme.  */
440   if (p->magic_biscuit != SIZEOF_PER_PROCESS)
441     api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
442                p->magic_biscuit, SIZEOF_PER_PROCESS);
443
444   /* Complain if incompatible API changes made */
445   if (p->api_major > cygwin_version.api_major)
446     api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
447                p->api_major, cygwin_version.api_major);
448
449   if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
450       CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
451     signal_shift_subtract = 0;
452 }
453
454 child_info NO_COPY *child_proc_info = NULL;
455 static MEMORY_BASIC_INFORMATION NO_COPY sm;
456
457 #define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
458                      PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
459
460 static void
461 alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
462 {
463   void *new_stack_pointer;
464   MEMORY_BASIC_INFORMATION m;
465   void *newbase;
466   int newlen;
467   LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
468   bool noguard;
469
470   if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
471     {
472       newbase = curbot;
473       newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
474       noguard = 1;
475     }
476   else
477     {
478       newbase = ci->stacktop;
479       newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
480       noguard = 0;
481     }
482   if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
483     api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
484                 ci->stacktop, ci->stackbottom);
485
486   new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
487
488   if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
489                      PAGE_EXECUTE_READWRITE))
490     api_fatal ("fork: can't commit memory for stack %p(%d), %E",
491                new_stack_pointer, ci->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   ci->stacktop = m.BaseAddress;
505   b[0] = '\0';
506 }
507
508 /* extend the stack prior to fork longjmp */
509
510 static void
511 alloc_stack (child_info_fork *ci)
512 {
513   /* FIXME: adding 16384 seems to avoid a stack copy problem during
514      fork on Win95, but I don't know exactly why yet. DJ */
515   volatile char b[ci->stacksize + 16384];
516
517   if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
518     api_fatal ("fork: couldn't get stack info, %E");
519
520   if (sm.AllocationBase == ci->stacktop)
521     ci->stacksize = 0;
522   else
523     alloc_stack_hard_way (ci, b + sizeof (b) - 1);
524
525   return;
526 }
527
528 #ifdef DEBUGGING
529 void
530 break_here ()
531 {
532   debug_printf ("break here");
533 }
534 #endif
535
536 static void
537 initial_env ()
538 {
539   char buf[CYG_MAX_PATH + 1];
540   if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
541     _cygwin_testing = 1;
542
543 #ifdef DEBUGGING
544   DWORD len;
545
546   if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
547     {
548       DWORD ms = atoi (buf);
549       buf[0] = '\0';
550       len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
551       console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
552       Sleep (ms);
553       if (!strace.active)
554         {
555           strace.inited = 0;
556           strace.hello ();
557         }
558     }
559   if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
560     {
561       char buf1[CYG_MAX_PATH + 1];
562       len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH);
563       strlwr (buf1);
564       strlwr (buf);
565       char *p = strchr (buf, ':');
566       if (!p)
567         p = (char *) "gdb.exe -nw";
568       else
569         *p++ = '\0';
570       if (strstr (buf1, buf))
571         {
572           error_start_init (p);
573           try_to_debug ();
574           console_printf ("*** Sending Break.  gdb may issue spurious SIGTRAP message.\n");
575           DebugBreak ();
576           break_here ();
577         }
578     }
579 #endif
580
581 }
582
583 void __stdcall
584 dll_crt0_0 ()
585 {
586   wincap.init ();
587   initial_env ();
588
589   char zeros[sizeof (child_proc_info->zero)] = {0};
590
591   init_console_handler ();
592   init_global_security ();
593   if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
594                        GetCurrentProcess (), &hMainProc, 0, FALSE,
595                         DUPLICATE_SAME_ACCESS))
596     hMainProc = GetCurrentProcess ();
597
598   DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
599                    &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
600
601   (void) SetErrorMode (SEM_FAILCRITICALERRORS);
602
603   STARTUPINFO si;
604   GetStartupInfo (&si);
605   child_proc_info = (child_info *) si.lpReserved2;
606
607   if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info
608       || memcmp (child_proc_info->zero, zeros,
609                  sizeof (child_proc_info->zero)) != 0)
610     child_proc_info = NULL;
611   else
612     {
613       if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
614         multiple_cygwin_problem ("proc", child_proc_info->intro, 0);
615       else if (child_proc_info->intro == PROC_MAGIC_GENERIC
616                && child_proc_info->magic != CHILD_INFO_MAGIC)
617         multiple_cygwin_problem ("proc", child_proc_info->magic,
618                                  CHILD_INFO_MAGIC);
619       else if (child_proc_info->cygheap != (void *) &_cygheap_start)
620         multiple_cygwin_problem ("cygheap", (DWORD) child_proc_info->cygheap,
621                                  (DWORD) &_cygheap_start);
622       unsigned should_be_cb = 0;
623       switch (child_proc_info->type)
624         {
625           case _PROC_FORK:
626             user_data->forkee = true;
627             should_be_cb = sizeof (child_info_fork);
628             /* fall through */;
629           case _PROC_SPAWN:
630           case _PROC_EXEC:
631             if (!should_be_cb)
632               should_be_cb = sizeof (child_info);
633             if (should_be_cb != child_proc_info->cb)
634               multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb);
635             else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb)
636               multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union));
637             else
638               {
639                 cygwin_user_h = child_proc_info->user_h;
640                 break;
641               }
642           default:
643             system_printf ("unknown exec type %d", child_proc_info->type);
644             /* intentionally fall through */
645           case _PROC_WHOOPS:
646             child_proc_info = NULL;
647             break;
648         }
649     }
650
651   device::init ();
652   do_global_ctors (&__CTOR_LIST__, 1);
653   cygthread::init ();
654
655   if (!child_proc_info)
656     memory_init ();
657   else
658     {
659       bool close_ppid_handle = false;
660       bool close_hexec_proc = false;
661       switch (child_proc_info->type)
662         {
663           case _PROC_FORK:
664             alloc_stack (fork_info);
665             cygheap_fixup_in_child (false);
666             memory_init ();
667             set_myself (NULL);
668             close_ppid_handle = !!child_proc_info->pppid_handle;
669             break;
670           case _PROC_SPAWN:
671             /* Have to delay closes until after cygheap is setup */
672             close_hexec_proc = !!spawn_info->hexec_proc;
673             close_ppid_handle = !!child_proc_info->pppid_handle;
674             goto around;
675           case _PROC_EXEC:
676             hexec_proc = spawn_info->hexec_proc;
677           around:
678             HANDLE h;
679             cygheap_fixup_in_child (true);
680             memory_init ();
681             if (!spawn_info->moreinfo->myself_pinfo ||
682                 !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
683                                   hMainProc, &h, 0, FALSE,
684                                   DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
685               h = NULL;
686             set_myself (h);
687             __argc = spawn_info->moreinfo->argc;
688             __argv = spawn_info->moreinfo->argv;
689             envp = spawn_info->moreinfo->envp;
690             envc = spawn_info->moreinfo->envc;
691             cygheap->fdtab.fixup_after_exec ();
692             signal_fixup_after_exec ();
693             if (spawn_info->moreinfo->old_title)
694               {
695                 old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
696                 cfree (spawn_info->moreinfo->old_title);
697               }
698             break;
699         }
700       if (close_hexec_proc)
701         CloseHandle (spawn_info->hexec_proc);
702       if (close_ppid_handle)
703         CloseHandle (child_proc_info->pppid_handle);
704     }
705
706   _cygtls::init ();
707
708   /* Initialize events */
709   events_init ();
710
711   cygheap->cwd.init ();
712 }
713
714 /* Take over from libc's crt0.o and start the application. Note the
715    various special cases when Cygwin DLL is being runtime loaded (as
716    opposed to being link-time loaded by Cygwin apps) from a non
717    cygwin app via LoadLibrary.  */
718 static void
719 dll_crt0_1 (char *)
720 {
721   /* According to onno@stack.urc.tue.nl, the exception handler record must
722      be on the stack.  */
723   /* FIXME: Verify forked children get their exception handler set up ok. */
724   exception_list cygwin_except_entry;
725
726   check_sanity_and_sync (user_data);
727   malloc_init ();
728
729   /* Initialize SIGSEGV handling, etc. */
730   init_exceptions (&cygwin_except_entry);
731
732   user_data->resourcelocks->Init ();
733   user_data->threadinterface->Init ();
734   ProtectHandle (hMainProc);
735   ProtectHandle (hMainThread);
736
737   /* Initialize pthread mainthread when not forked and it is safe to call new,
738      otherwise it is reinitalized in fixup_after_fork */
739   if (!user_data->forkee)
740     pthread::init_mainthread ();
741
742 #ifdef DEBUGGING
743   strace.microseconds ();
744 #endif
745
746   /* Initialize debug muto, if DLL is built with --enable-debugging.
747      Need to do this before any helper threads start. */
748   debug_init ();
749
750 #ifdef NEWVFORK
751   cygheap->fdtab.vfork_child_fixup ();
752   main_vfork = vfork_storage.create ();
753 #endif
754
755   cygbench ("pre-forkee");
756   if (user_data->forkee)
757     {
758       /* If we've played with the stack, stacksize != 0.  That means that
759          fork() was invoked from other than the main thread.  Make sure that
760          frame pointer is referencing the new stack so that the OS knows what
761          to do when it needs to increase the size of the stack.
762
763          NOTE: Don't do anything that involves the stack until you've completed
764          this step. */
765       if (fork_info->stacksize)
766         {
767           _tlsbase = (char *) fork_info->stackbottom;
768           _tlstop = (char *) fork_info->stacktop;
769         }
770       longjmp (fork_info->jmp, true);
771     }
772
773 #ifdef DEBUGGING
774   {
775   extern void fork_init ();
776   fork_init ();
777   }
778 #endif
779
780   /* Initialize our process table entry. */
781   pinfo_init (envp, envc);
782
783   if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
784       old_title = title_buf;
785
786   /* Allocate cygheap->fdtab */
787   dtable_init ();
788
789   /* Initialize user info. */
790   uinfo_init ();
791
792   /* Initialize signal/subprocess handling. */
793   sigproc_init ();
794
795   /* Connect to tty. */
796   tty_init ();
797
798   if (!__argc)
799     {
800       char *line = GetCommandLineA ();
801       line = strcpy ((char *) alloca (strlen (line) + 1), line);
802
803       if (current_codepage == oem_cp)
804         CharToOemA (line, line);
805
806       /* Scan the command line and build argv.  Expand wildcards if not
807          called from another cygwin process. */
808       build_argv (line, __argv, __argc,
809                   NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
810
811       /* Convert argv[0] to posix rules if it's currently blatantly
812          win32 style. */
813       if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
814         {
815           char *new_argv0 = (char *) malloc (CYG_MAX_PATH);
816           cygwin_conv_to_posix_path (__argv[0], new_argv0);
817           __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
818         }
819     }
820
821   __argc_safe = __argc;
822   if (user_data->premain[0])
823     for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
824       user_data->premain[i] (__argc, __argv, user_data);
825
826   /* Set up standard fds in file descriptor table. */
827   cygheap->fdtab.stdio_init ();
828
829   /* Set up __progname for getopt error call. */
830   if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
831     ++__progname;
832   else
833     __progname = __argv[0];
834   if (__progname)
835     {
836       char *cp = strchr (__progname, '\0') - 4;
837       if (cp > __progname && strcasematch (cp, ".exe"))
838         *cp = '\0';
839     }
840
841   /* Set new console title if appropriate. */
842
843   if (display_title && !dynamically_loaded)
844     {
845       char *cp = __progname;
846       if (strip_title_path)
847         for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
848           if (isdirsep (*ptr))
849             cp = ptr + 1;
850       set_console_title (cp);
851     }
852
853   cygwin_finished_initializing = true;
854   /* Call init of loaded dlls. */
855   dlls.init ();
856
857   /* Execute any specified "premain" functions */
858   if (user_data->premain[PREMAIN_LEN / 2])
859     for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
860       user_data->premain[i] (__argc, __argv, user_data);
861
862   debug_printf ("user_data->main %p", user_data->main);
863
864   if (dynamically_loaded)
865     {
866       set_errno (0);
867       return;
868     }
869
870   /* Disable case-insensitive globbing */
871   ignore_case_with_glob = false;
872
873
874   set_errno (0);
875
876   MALLOC_CHECK;
877   cygbench (__progname);
878
879   /* Flush signals and ensure that signal thread is up and running. Can't
880      do this for noncygwin case since the signal thread is blocked due to
881      LoadLibrary serialization. */
882   wait_for_sigthread ();
883   if (user_data->main)
884     exit (user_data->main (__argc, __argv, *user_data->envptr));
885 }
886
887 struct _reent *
888 initialize_main_tls (char *padding)
889 {
890   if (!_main_tls)
891     {
892       _main_tls = &_my_tls;
893       _main_tls->init_thread (padding, NULL);
894     }
895   return &_main_tls->local_clib;
896 }
897
898 /* Wrap the real one, otherwise gdb gets confused about
899    two symbols with the same name, but different addresses.
900
901    UPTR is a pointer to global data that lives on the libc side of the
902    line [if one distinguishes the application from the dll].  */
903
904 extern "C" void __stdcall
905 _dll_crt0 ()
906 {
907   extern HANDLE sync_startup;
908   extern unsigned threadfunc_ix;
909   if (threadfunc_ix)
910     /* nothing to do */;
911   else if (!sync_startup)
912     system_printf ("internal error: sync_startup not called at start.  Expect signal problems.");
913   else
914     {
915       (void) WaitForSingleObject (sync_startup, INFINITE);
916       CloseHandle (sync_startup);
917     }
918
919   if (!threadfunc_ix)
920     system_printf ("internal error: couldn't determine location of thread function on stack.  Expect signal problems.");
921
922   main_environ = user_data->envptr;
923   *main_environ = NULL;
924
925   char padding[CYGTLS_PADSIZE];
926   _impure_ptr = _GLOBAL_REENT;
927   _impure_ptr->_stdin = &_impure_ptr->__sf[0];
928   _impure_ptr->_stdout = &_impure_ptr->__sf[1];
929   _impure_ptr->_stderr = &_impure_ptr->__sf[2];
930   _impure_ptr->_current_locale = "C";
931
932   if (child_proc_info && child_proc_info->type == _PROC_FORK)
933     user_data->forkee = true;
934   else
935     __sinit (_impure_ptr);
936
937   initialize_main_tls (padding);
938   dll_crt0_1 (padding);
939 }
940
941 void
942 dll_crt0 (per_process *uptr)
943 {
944   /* Set the local copy of the pointer into the user space. */
945   if (uptr && uptr != user_data)
946     {
947       memcpy (user_data, uptr, per_process_overwrite);
948       *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
949     }
950   _dll_crt0 ();
951 }
952
953 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll */
954 extern "C" void
955 cygwin_dll_init ()
956 {
957   static char **envp;
958   static int _fmode;
959
960   if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
961                        GetCurrentProcess (), &hMainProc, 0, FALSE,
962                         DUPLICATE_SAME_ACCESS))
963     hMainProc = GetCurrentProcess ();
964
965   DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
966                    &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
967   user_data->magic_biscuit = sizeof (per_process);
968
969   user_data->envptr = &envp;
970   user_data->fmode_ptr = &_fmode;
971
972   dll_crt0_1 (NULL);
973 }
974
975 extern "C" void
976 __main (void)
977 {
978   do_global_ctors (user_data->ctors, false);
979   atexit (do_global_dtors);
980 }
981
982 exit_states NO_COPY exit_state;
983 extern CRITICAL_SECTION exit_lock;
984
985 void __stdcall
986 do_exit (int status)
987 {
988   syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
989
990 #ifdef NEWVFORK
991   vfork_save *vf = vfork_storage.val ();
992   if (vf != NULL && vf->pid < 0)
993     {
994       exit_state = ES_NOT_EXITING;
995       vf->restore_exit (status);
996     }
997 #endif
998
999   EnterCriticalSection (&exit_lock);
1000   muto::set_exiting_thread ();
1001   if (exit_state < ES_EVENTS_TERMINATE)
1002     {
1003       exit_state = ES_EVENTS_TERMINATE;
1004       events_terminate ();
1005     }
1006
1007   UINT n = (UINT) status;
1008   if (exit_state < ES_THREADTERM)
1009     {
1010       exit_state = ES_THREADTERM;
1011       cygthread::terminate ();
1012     }
1013
1014   if (exit_state < ES_SIGNAL)
1015     {
1016       exit_state = ES_SIGNAL;
1017       if (!(n & EXIT_REPARENTING))
1018         {
1019           signal (SIGCHLD, SIG_IGN);
1020           signal (SIGHUP, SIG_IGN);
1021           signal (SIGINT, SIG_IGN);
1022           signal (SIGQUIT, SIG_IGN);
1023         }
1024     }
1025
1026   if (exit_state < ES_CLOSEALL)
1027     {
1028       exit_state = ES_CLOSEALL;
1029       close_all_files ();
1030     }
1031
1032   if (exit_state < ES_SIGPROCTERMINATE)
1033     {
1034       exit_state = ES_SIGPROCTERMINATE;
1035       sigproc_terminate ();
1036     }
1037
1038   myself->stopsig = 0;
1039   if (exit_state < ES_TITLE)
1040     {
1041       exit_state = ES_TITLE;
1042       /* restore console title */
1043       if (old_title && display_title)
1044         set_console_title (old_title);
1045     }
1046
1047   if (exit_state < ES_HUP_PGRP)
1048     {
1049       exit_state = ES_HUP_PGRP;
1050       /* Kill orphaned children on group leader exit */
1051       if (myself->has_pgid_children && myself->pid == myself->pgid)
1052         {
1053           siginfo_t si;
1054           si.si_signo = -SIGHUP;
1055           si.si_code = SI_KERNEL;
1056           si.si_pid = si.si_uid = si.si_errno = 0;
1057           sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1058                           myself->pid, myself->pgid);
1059           kill_pgrp (myself->pgid, si);
1060         }
1061     }
1062
1063   if (exit_state < ES_HUP_SID)
1064     {
1065       exit_state = ES_HUP_SID;
1066       /* Kill the foreground process group on session leader exit */
1067       if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1068         {
1069           tty *tp = cygwin_shared->tty[myself->ctty];
1070           sigproc_printf ("%d == sid %d, send SIGHUP to children",
1071                           myself->pid, myself->sid);
1072
1073         /* CGF FIXME: This can't be right. */
1074           if (tp->getsid () == myself->sid)
1075             tp->kill_pgrp (SIGHUP);
1076         }
1077
1078     }
1079
1080   if (exit_state < ES_TTY_TERMINATE)
1081     {
1082       exit_state = ES_TTY_TERMINATE;
1083       tty_terminate ();
1084     }
1085
1086   minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
1087   myself->exit (n);
1088 }
1089
1090 static muto *atexit_lock;
1091
1092 extern "C" int
1093 cygwin_atexit (void (*function)(void))
1094 {
1095   int res;
1096   if (!atexit_lock)
1097     new_muto (atexit_lock);
1098   atexit_lock->acquire ();
1099   res = atexit (function);
1100   atexit_lock->release ();
1101   return res;
1102 }
1103
1104 extern "C" void
1105 cygwin_exit (int n)
1106 {
1107   if (atexit_lock)
1108     atexit_lock->acquire ();
1109   exit (n);
1110 }
1111
1112 extern "C" void
1113 _exit (int n)
1114 {
1115   do_exit ((DWORD) n & 0xffff);
1116 }
1117
1118 extern "C" void
1119 __api_fatal (const char *fmt, ...)
1120 {
1121   char buf[4096];
1122   va_list ap;
1123
1124   va_start (ap, fmt);
1125   int n = __small_sprintf (buf, "%P (%u): *** ", cygwin_pid (GetCurrentProcessId ()));
1126   __small_vsprintf (buf + n, fmt, ap);
1127   va_end (ap);
1128   strcat (buf, "\n");
1129   int len = strlen (buf);
1130   DWORD done;
1131   (void) WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, len, &done, 0);
1132
1133   /* Make sure that the message shows up on the screen, too, since this is
1134      a serious error. */
1135   if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)
1136     {
1137       HANDLE h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
1138                              FILE_SHARE_WRITE | FILE_SHARE_WRITE,
1139                              &sec_none, OPEN_EXISTING, 0, 0);
1140       if (h != INVALID_HANDLE_VALUE)
1141         (void) WriteFile (h, buf, len, &done, 0);
1142     }
1143
1144   /* We are going down without mercy.  Make sure we reset
1145      our process_state. */
1146   sigproc_terminate ();
1147 #ifdef DEBUGGING
1148   (void) try_to_debug ();
1149 #endif
1150   myself->exit (1);
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 version mismatch detected - %p/%p.\n\
1170 You have multiple copies of cygwin1.dll on your system.\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.", what, magic_version, version);
1175 }
1176
1177 #ifdef DEBUGGING
1178 void __stdcall
1179 cygbench (const char *s)
1180 {
1181   char buf[1024];
1182   if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1183     small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1184 }
1185 #endif