OSDN Git Service

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