]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/dcrt0.cc
* environ.cc (environ_init): Avoid a compiler warning.
[newlib-cygwin.git] / winsup / cygwin / dcrt0.cc
CommitLineData
1fd5e000
CF
1/* dcrt0.cc -- essentially the main() for the Cygwin dll
2
33ad2bf9 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
1fd5e000
CF
4
5This file is part of Cygwin.
6
7This software is a copyrighted work licensed under the terms of the
8Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9details. */
10
4c8d72de 11#include "winsup.h"
1fd5e000
CF
12#include <unistd.h>
13#include <stdlib.h>
1fd5e000
CF
14#include "glob.h"
15#include "exceptions.h"
1fd5e000 16#include <ctype.h>
166b2571 17#include <limits.h>
ee1d77e4
CF
18#include <wingdi.h>
19#include <winuser.h>
df63bd49 20#include <errno.h>
bccd5e0d 21#include "sigproc.h"
e2ebe117 22#include "pinfo.h"
9e2baf8d 23#include "cygerrno.h"
f0338f54 24#define NEED_VFORK
95a8465b 25#include "perprocess.h"
6b91b8d5 26#include "security.h"
0381fec6 27#include "fhandler.h"
ac5561f2 28#include "path.h"
47063f00 29#include "dtable.h"
0381fec6 30#include "cygheap.h"
77f4a250 31#include "child_info_magic.h"
0381fec6 32#include "perthread.h"
29ac7f89 33#include "shared_info.h"
f0338f54 34#include "cygwin_version.h"
f0338f54 35#include "dll_init.h"
b6bd7037 36#include "cygthread.h"
1fd5e000
CF
37
38#define MAX_AT_FILE_LEVEL 10
39
0312ede4 40#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
14a3bc2f 41
b6bd7037
CF
42HANDLE NO_COPY hMainProc;
43HANDLE NO_COPY hMainThread;
1fd5e000 44
12e659ef
CF
45sigthread NO_COPY mainthread; // ID of the main thread
46
1fd5e000
CF
47per_thread_waitq NO_COPY waitq_storage;
48per_thread_vfork NO_COPY vfork_storage;
49per_thread_signal_dispatch NO_COPY signal_dispatch_storage;
50
51per_thread NO_COPY *threadstuff[] = {&waitq_storage,
52 &vfork_storage,
53 &signal_dispatch_storage,
54 NULL};
55
08b78edf
CF
56BOOL display_title;
57BOOL strip_title_path;
1fd5e000 58BOOL allow_glob = TRUE;
ee1d77e4 59codepage_type current_codepage = ansi_cp;
1fd5e000 60
08b78edf 61int cygwin_finished_initializing;
1fd5e000
CF
62
63/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
64 This is subtracted from the signal number prior to shifting the bit.
65 In older versions of cygwin, the signal was used as-is to shift the
66 bit for masking. So, we'll temporarily detect this and set it to zero
67 for programs that are linked using older cygwins. This is just a stopgap
68 measure to allow an orderly transfer to the new, correct sigmask method. */
57c89867 69unsigned NO_COPY int signal_shift_subtract = 1;
1fd5e000 70
737a86d3 71ResourceLocks _reslock NO_COPY;
f9229ef7 72MTinterface _mtinterf;
737a86d3 73
9867ecfd 74bool NO_COPY _cygwin_testing;
57013c31 75unsigned NO_COPY _cygwin_testing_magic;
9867ecfd 76
179cae11
CF
77char NO_COPY almost_null[1];
78
1fd5e000
CF
79extern "C"
80{
81 /* This is an exported copy of environ which can be used by DLLs
82 which use cygwin.dll. */
83 char **__cygwin_environ;
2eb392bd 84 char ***main_environ;
1fd5e000 85 /* __progname used in getopt error message */
08b78edf 86 char *__progname;
f97e7d75 87 struct _reent reent_data = _REENT_INIT(reent_data);
737a86d3
CF
88 struct per_process __cygwin_user_data =
89 {/* initial_sp */ 0, /* magic_biscuit */ 0,
90 /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
91 /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
a0f7b496 92 /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
c7e2187a
CF
93 /* malloc */ malloc, /* free */ free,
94 /* realloc */ realloc,
737a86d3
CF
95 /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
96 /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
97 /* bss_start */ NULL, /* bss_end */ NULL,
c7e2187a 98 /* calloc */ calloc,
737a86d3
CF
99 /* premain */ {NULL, NULL, NULL, NULL},
100 /* run_ctors_p */ 0,
1ff9f4b9
CF
101 /* unused */ {0, 0, 0, 0, 0, 0, 0},
102 /* forkee */ 0,
103 /* hmodule */ NULL,
737a86d3
CF
104 /* api_major */ CYGWIN_VERSION_API_MAJOR,
105 /* api_minor */ CYGWIN_VERSION_API_MINOR,
106 /* unused2 */ {0, 0, 0, 0, 0},
107 /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
108 /* impure_ptr */ &reent_data,
109 };
08b78edf 110 bool ignore_case_with_glob;
79201150 111 int __declspec (dllexport) _check_for_executable = TRUE;
95a8465b 112#ifdef DEBUGGING
08b78edf 113 int pinger;
95a8465b 114#endif
1fd5e000
CF
115};
116
08b78edf 117char *old_title;
1fd5e000
CF
118char title_buf[TITLESIZE + 1];
119
120static void
121do_global_dtors (void)
122{
123 if (user_data->dtors)
124 {
125 void (**pfunc)() = user_data->dtors;
126 while (*++pfunc)
127 (*pfunc) ();
128 }
129}
130
131static void __stdcall
132do_global_ctors (void (**in_pfunc)(), int force)
133{
134 if (!force)
135 {
136 if (user_data->forkee || user_data->run_ctors_p)
b0e82b74 137 return; // inherit constructed stuff from parent pid
1fd5e000
CF
138 user_data->run_ctors_p = 1;
139 }
140
141 /* Run ctors backwards, so skip the first entry and find how many
142 there are, then run them. */
143
144 void (**pfunc)() = in_pfunc;
145
146 while (*++pfunc)
147 ;
148 while (--pfunc > in_pfunc)
149 (*pfunc) ();
150
14a3bc2f 151 if (user_data->magic_biscuit == SIZEOF_PER_PROCESS)
1fd5e000
CF
152 atexit (do_global_dtors);
153}
154
1fd5e000 155/*
052e90e9
CF
156 * Replaces @file in the command line with the contents of the file.
157 * There may be multiple @file's in a single command line
158 * A \@file is replaced with @file so that echo \@foo would print
159 * @foo and not the contents of foo.
1fd5e000
CF
160 */
161static int __stdcall
eafa31fb 162insert_file (char *name, char *&cmd)
1fd5e000
CF
163{
164 HANDLE f;
165 DWORD size;
166
167 f = CreateFile (name + 1,
168 GENERIC_READ, /* open for reading */
169 FILE_SHARE_READ, /* share for reading */
170 &sec_none_nih, /* no security */
171 OPEN_EXISTING, /* existing file only */
172 FILE_ATTRIBUTE_NORMAL, /* normal file */
173 NULL); /* no attr. template */
174
175 if (f == INVALID_HANDLE_VALUE)
176 {
177 debug_printf ("couldn't open file '%s', %E", name);
178 return FALSE;
179 }
180
181 /* This only supports files up to about 4 billion bytes in
182 size. I am making the bold assumption that this is big
183 enough for this feature */
184 size = GetFileSize (f, NULL);
185 if (size == 0xFFFFFFFF)
186 {
187 debug_printf ("couldn't get file size for '%s', %E", name);
188 return FALSE;
189 }
190
191 int new_size = strlen (cmd) + size + 2;
192 char *tmp = (char *) malloc (new_size);
193 if (!tmp)
194 {
195 debug_printf ("malloc failed, %E");
196 return FALSE;
197 }
198
199 /* realloc passed as it should */
200 DWORD rf_read;
201 BOOL rf_result;
202 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
203 CloseHandle (f);
204 if (!rf_result || (rf_read != size))
205 {
206 debug_printf ("ReadFile failed, %E");
207 return FALSE;
208 }
209
210 tmp[size++] = ' ';
211 strcpy (tmp + size, cmd);
212 cmd = tmp;
213 return TRUE;
214}
215
216static inline int
217isquote (char c)
218{
219 char ch = c;
220 return ch == '"' || ch == '\'';
221}
222
223/* Step over a run of characters delimited by quotes */
8e382d80 224static /*__inline*/ char *
9cec3d45 225quoted (char *cmd, int winshell)
1fd5e000
CF
226{
227 char *p;
228 char quote = *cmd;
229
b0e82b74 230 if (!winshell)
1fd5e000 231 {
b0e82b74
CF
232 char *p;
233 strcpy (cmd, cmd + 1);
234 if ((p = strchr (cmd, quote)) != NULL)
235 strcpy (p, p + 1);
4f46dbc7
CF
236 else
237 p = strchr (cmd, '\0');
99d7d12a 238 return p;
1fd5e000
CF
239 }
240
4eafa56e 241 const char *s = quote == '\'' ? "'" : "\\\"";
b0e82b74
CF
242 /* This must have been run from a Windows shell, so preserve
243 quotes for globify to play with later. */
4eafa56e
CF
244 while (*cmd && *++cmd)
245 if ((p = strpbrk (cmd, s)) == NULL)
b0e82b74
CF
246 {
247 cmd = strchr (cmd, '\0'); // no closing quote
248 break;
249 }
b0e82b74
CF
250 else if (*p == '\\')
251 cmd = ++p;
4eafa56e 252 else if (quote == '"' && p[1] == '"')
b0e82b74
CF
253 {
254 *p = '\\';
255 cmd = ++p; // a quoted quote
256 }
257 else
258 {
259 cmd = p + 1; // point to after end
260 break;
261 }
262 return cmd;
1fd5e000
CF
263}
264
265/* Perform a glob on word if it contains wildcard characters.
266 Also quote every character between quotes to force glob to
267 treat the characters literally. */
268static int __stdcall
269globify (char *word, char **&argv, int &argc, int &argvlen)
270{
271 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
272 return 0;
273
274 int n = 0;
275 char *p, *s;
75858e8a 276 int dos_spec = isdrive (word);
0312ede4 277 if (!dos_spec && isquote (*word) && word[1] && word[2])
75858e8a 278 dos_spec = isdrive (word + 1);
1fd5e000
CF
279
280 /* We'll need more space if there are quoting characters in
281 word. If that is the case, doubling the size of the
282 string should provide more than enough space. */
283 if (strpbrk (word, "'\""))
284 n = strlen (word);
285 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
286
287 /* Fill pattern with characters from word, quoting any
288 characters found within quotes. */
289 for (p = pattern, s = word; *s != '\000'; s++, p++)
290 if (!isquote (*s))
291 {
292 if (dos_spec && *s == '\\')
293 *p++ = '\\';
294 *p = *s;
295 }
296 else
297 {
298 char quote = *s;
299 while (*++s && *s != quote)
300 {
25ba8f30 301 if (dos_spec || *s != '\\')
c845acff 302 /* nothing */;
c845acff 303 else if (s[1] == quote || s[1] == '\\')
1fd5e000
CF
304 s++;
305 *p++ = '\\';
306 *p++ = *s;
307 }
308 if (*s == quote)
309 p--;
310 if (*s == '\0')
311 break;
312 }
313
314 *p = '\0';
315
316 glob_t gl;
317 gl.gl_offs = 0;
318
319 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
320 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
321 return 0;
322
323 /* Allocate enough space in argv for the matched filenames. */
324 n = argc;
325 if ((argc += gl.gl_pathc) > argvlen)
326 {
327 argvlen = argc + 10;
328 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
329 }
330
331 /* Copy the matched filenames to argv. */
332 char **gv = gl.gl_pathv;
333 char **av = argv + n;
334 while (*gv)
335 {
336 debug_printf ("argv[%d] = '%s'\n", n++, *gv);
337 *av++ = *gv++;
338 }
339
340 /* Clean up after glob. */
341 free (gl.gl_pathv);
342 return 1;
343}
344
345/* Build argv, argc from string passed from Windows. */
346
347static void __stdcall
348build_argv (char *cmd, char **&argv, int &argc, int winshell)
349{
350 int argvlen = 0;
1fd5e000
CF
351 int nesting = 0; // monitor "nesting" from insert_file
352
353 argc = 0;
354 argvlen = 0;
355 argv = NULL;
356
357 /* Scan command line until there is nothing left. */
358 while (*cmd)
359 {
360 /* Ignore spaces */
361 if (issep (*cmd))
362 {
363 cmd++;
364 continue;
365 }
366
367 /* Found the beginning of an argument. */
368 char *word = cmd;
369 char *sawquote = NULL;
370 while (*cmd)
371 {
372 if (*cmd != '"' && (!winshell || *cmd != '\''))
373 cmd++; // Skip over this character
374 else
375 /* Skip over characters until the closing quote */
376 {
377 sawquote = cmd;
2768430b 378 cmd = quoted (cmd, winshell && argc > 0);
1fd5e000
CF
379 }
380 if (issep (*cmd)) // End of argument if space
381 break;
382 }
383 if (*cmd)
384 *cmd++ = '\0'; // Terminate `word'
385
386 /* Possibly look for @file construction assuming that this isn't
387 the very first argument and the @ wasn't quoted */
388 if (argc && sawquote != word && *word == '@')
389 {
390 if (++nesting > MAX_AT_FILE_LEVEL)
391 api_fatal ("Too many levels of nesting for %s", word);
eafa31fb 392 if (insert_file (word, cmd))
1fd5e000 393 continue; // There's new stuff in cmd now
1fd5e000
CF
394 }
395
396 /* See if we need to allocate more space for argv */
397 if (argc >= argvlen)
398 {
399 argvlen = argc + 10;
400 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
401 }
402
403 /* Add word to argv file after (optional) wildcard expansion. */
404 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
405 {
406 debug_printf ("argv[%d] = '%s'\n", argc, word);
407 argv[argc++] = word;
408 }
409 }
410
411 argv[argc] = NULL;
b0e82b74
CF
412
413 debug_printf ("argc %d", argc);
1fd5e000
CF
414}
415
416/* sanity and sync check */
417void __stdcall
418check_sanity_and_sync (per_process *p)
419{
420 /* Sanity check to make sure developers didn't change the per_process */
421 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
422 /* about changing it]. */
423 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
424 {
425 api_fatal ("per_process sanity check failed");
426 }
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
6ea3e429 450child_info NO_COPY *child_proc_info = NULL;
109e4822 451static MEMORY_BASIC_INFORMATION NO_COPY sm;
1fd5e000 452
a54ad580
CF
453#define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
454 PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
e13ea334 455
b0e82b74
CF
456// __inline__ void
457extern void
1fd5e000
CF
458alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
459{
460 void *new_stack_pointer;
461 MEMORY_BASIC_INFORMATION m;
b0e82b74
CF
462 void *newbase;
463 int newlen;
464 LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
465 bool noguard;
1fd5e000 466
b0e82b74
CF
467 if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
468 {
469 newbase = curbot;
470 newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
471 noguard = 1;
472 }
473 else
474 {
475 newbase = ci->stacktop;
476 newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
477 noguard = 0;
478 }
479 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
1fd5e000
CF
480 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
481 ci->stacktop, ci->stackbottom);
482
483 new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
484
485 if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
486 PAGE_EXECUTE_READWRITE))
487 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
488 new_stack_pointer, ci->stacksize);
489 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
490 api_fatal ("fork: couldn't get new stack info, %E");
b0e82b74
CF
491 if (!noguard)
492 {
493 m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
494 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
a54ad580 495 CYGWIN_GUARD))
b0e82b74
CF
496 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
497 m.BaseAddress);
498 }
1fd5e000
CF
499 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
500 api_fatal ("fork: couldn't get new stack info, %E");
501 ci->stacktop = m.BaseAddress;
502 *b = 0;
503}
504
505/* extend the stack prior to fork longjmp */
506
b0e82b74 507static void
1fd5e000
CF
508alloc_stack (child_info_fork *ci)
509{
510 /* FIXME: adding 16384 seems to avoid a stack copy problem during
511 fork on Win95, but I don't know exactly why yet. DJ */
512 volatile char b[ci->stacksize + 16384];
513
57013c31
CF
514 if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
515 api_fatal ("fork: couldn't get stack info, %E");
1fd5e000 516
57013c31
CF
517 if (sm.AllocationBase != ci->stacktop)
518 alloc_stack_hard_way (ci, b + sizeof (b) - 1);
519 else
520 ci->stacksize = 0;
1fd5e000
CF
521
522 return;
523}
524
1fd5e000 525static NO_COPY int mypid = 0;
08b78edf
CF
526int _declspec(dllexport) __argc;
527char _declspec(dllexport) **__argv;
9661a0c8 528vfork_save NO_COPY *main_vfork = NULL;
1fd5e000 529
f343a326
CF
530void
531sigthread::init (const char *s)
532{
c0188ae7 533 InitializeCriticalSection (&lock);
167095f6 534 id = GetCurrentThreadId ();
f343a326
CF
535}
536
1fd5e000
CF
537/* Take over from libc's crt0.o and start the application. Note the
538 various special cases when Cygwin DLL is being runtime loaded (as
539 opposed to being link-time loaded by Cygwin apps) from a non
540 cygwin app via LoadLibrary. */
541static void
542dll_crt0_1 ()
543{
b0e82b74
CF
544 /* According to onno@stack.urc.tue.nl, the exception handler record must
545 be on the stack. */
546 /* FIXME: Verify forked children get their exception handler set up ok. */
547 exception_list cygwin_except_entry;
1fd5e000 548
2a6fc028 549 /* Initialize SIGSEGV handling, etc. */
b0e82b74
CF
550 init_exceptions (&cygwin_except_entry);
551
b0e82b74 552 /* Set the os_being_run global. */
ba946828 553 wincap.init ();
1fd5e000
CF
554 check_sanity_and_sync (user_data);
555
fe4283af
CF
556 do_global_ctors (&__CTOR_LIST__, 1);
557
1fd5e000
CF
558 /* Nasty static stuff needed by newlib -- point to a local copy of
559 the reent stuff.
560 Note: this MUST be done here (before the forkee code) as the
561 fork copy code doesn't copy the data in libccrt0.cc (that's why we
562 pass in the per_process struct into the .dll from libccrt0). */
563
1fd5e000
CF
564 _impure_ptr = &reent_data;
565
b0e82b74 566 user_data->resourcelocks->Init ();
166b2571 567 user_data->threadinterface->Init (user_data->forkee);
4f7ac76a 568
c0188ae7
CF
569 mainthread.init ("mainthread"); // For use in determining if signals
570 // should be blocked.
b0e82b74 571
166b2571 572 int envc = 0;
b0e82b74
CF
573 char **envp = NULL;
574
575 if (child_proc_info)
576 {
c03dba93
CF
577 bool close_ppid_handle = false;
578 bool close_hexec_proc = false;
77f4a250 579 switch (child_proc_info->type)
b0e82b74 580 {
57013c31 581 case _PROC_FORK:
6ea3e429 582 cygheap_fixup_in_child (0);
b0e82b74
CF
583 alloc_stack (fork_info);
584 set_myself (mypid);
c03dba93 585 close_ppid_handle = !!child_proc_info->pppid_handle;
b0e82b74 586 break;
57013c31 587 case _PROC_SPAWN:
c03dba93
CF
588 /* Have to delay closes until after cygheap is setup */
589 close_hexec_proc = !!spawn_info->hexec_proc;
590 close_ppid_handle = !!child_proc_info->pppid_handle;
166b2571 591 goto around;
57013c31 592 case _PROC_EXEC:
166b2571
CF
593 hexec_proc = spawn_info->hexec_proc;
594 around:
b0e82b74 595 HANDLE h;
6ea3e429 596 cygheap_fixup_in_child (1);
b0e82b74
CF
597 if (!spawn_info->moreinfo->myself_pinfo ||
598 !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
1dc16fc7
CF
599 hMainProc, &h, 0, 0,
600 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
b0e82b74
CF
601 h = NULL;
602 set_myself (mypid, h);
603 __argc = spawn_info->moreinfo->argc;
604 __argv = spawn_info->moreinfo->argv;
166b2571
CF
605 envp = spawn_info->moreinfo->envp;
606 envc = spawn_info->moreinfo->envc;
0381fec6 607 cygheap->fdtab.fixup_after_exec (spawn_info->parent);
166b2571 608 signal_fixup_after_exec (child_proc_info->type == PROC_SPAWN);
b0e82b74
CF
609 CloseHandle (spawn_info->parent);
610 if (spawn_info->moreinfo->old_title)
611 {
612 old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
613 cfree (spawn_info->moreinfo->old_title);
614 }
b0e82b74
CF
615 break;
616 }
c03dba93
CF
617 if (close_hexec_proc)
618 CloseHandle (spawn_info->hexec_proc);
619 if (close_ppid_handle)
620 CloseHandle (child_proc_info->pppid_handle);
b0e82b74 621 }
1fd5e000 622
1fd5e000 623 /* Initialize the cygwin subsystem if this is the first process,
6a4878cf
CF
624 or attach to shared data structures if it's already running. */
625 memory_init ();
b6bd7037 626 cygthread::init ();
3d0ba393 627
0301bfd0
CF
628 ProtectHandle (hMainProc);
629 ProtectHandle (hMainThread);
630
3d0ba393
CF
631 /* Initialize debug muto, if DLL is built with --enable-debugging.
632 Need to do this before any helper threads start. */
633 debug_init ();
634
0381fec6 635 cygheap->fdtab.vfork_child_fixup ();
1fd5e000 636
1fd5e000
CF
637 (void) SetErrorMode (SEM_FAILCRITICALERRORS);
638
1fd5e000
CF
639 /* Initialize events. */
640 events_init ();
641
431ba7dd 642 cygheap->cwd.init ();
9661a0c8 643 main_vfork = vfork_storage.create ();
6e8f36bc 644
166b2571 645 cygbench ("pre-forkee");
1fd5e000
CF
646 if (user_data->forkee)
647 {
648 /* If we've played with the stack, stacksize != 0. That means that
649 fork() was invoked from other than the main thread. Make sure that
650 frame pointer is referencing the new stack so that the OS knows what
651 to do when it needs to increase the size of the stack.
652
653 NOTE: Don't do anything that involves the stack until you've completed
654 this step. */
b0e82b74 655 if (fork_info->stacksize)
1fd5e000 656 {
b0e82b74
CF
657 asm ("movl %0,%%fs:4" : : "r" (fork_info->stackbottom));
658 asm ("movl %0,%%fs:8" : : "r" (fork_info->stacktop));
1fd5e000
CF
659 }
660
b0e82b74 661 longjmp (fork_info->jmp, fork_info->cygpid);
1fd5e000
CF
662 }
663
84aeff41
CF
664#ifdef DEBUGGING
665 {
666 extern void fork_init ();
667 fork_init ();
668 }
669#endif
670
b0e82b74 671 /* Initialize our process table entry. */
166b2571 672 pinfo_init (envp, envc);
1fd5e000
CF
673
674 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
675 old_title = title_buf;
676
0381fec6 677 /* Allocate cygheap->fdtab */
e2ebe117 678 dtable_init ();
1fd5e000 679
9a771b29
CF
680 /* Initialize uid, gid if necessary. */
681 if (child_proc_info == NULL || spawn_info->moreinfo->uid == ILLEGAL_UID)
682 uinfo_init ();
7054be8b 683
1fd5e000
CF
684 /* Initialize signal/subprocess handling. */
685 sigproc_init ();
686
687 /* Connect to tty. */
688 tty_init ();
689
b0e82b74 690 if (!__argc)
1fd5e000 691 {
166b2571
CF
692 char *line = GetCommandLineA ();
693 line = strcpy ((char *) alloca (strlen (line) + 1), line);
694
ee1d77e4 695 if (current_codepage == oem_cp)
077ec4cb 696 CharToOemA (line, line);
ee1d77e4 697
b0e82b74
CF
698 /* Scan the command line and build argv. Expand wildcards if not
699 called from another cygwin process. */
700 build_argv (line, __argv, __argc,
701 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
702
703 /* Convert argv[0] to posix rules if it's currently blatantly
704 win32 style. */
705 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
706 {
707 char *new_argv0 = (char *) alloca (MAX_PATH);
708 cygwin_conv_to_posix_path (__argv[0], new_argv0);
b0e82b74
CF
709 __argv[0] = new_argv0;
710 }
1fd5e000
CF
711 }
712
b0e82b74
CF
713 if (user_data->premain[0])
714 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
95a8465b 715 user_data->premain[i] (__argc, __argv, user_data);
b0e82b74 716
1ac6d1a1 717 /* Set up standard fds in file descriptor table. */
083abe54 718 cygheap->fdtab.stdio_init ();
1ac6d1a1 719
1fd5e000 720 /* Set up __progname for getopt error call. */
eba23038
CV
721 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
722 ++__progname;
723 else
724 __progname = __argv[0];
725 if (__progname)
726 {
727 char *cp = strchr (__progname, '\0') - 4;
728 if (cp > __progname && strcasematch (cp, ".exe"))
729 *cp = '\0';
730 }
1fd5e000 731
1dc16fc7
CF
732 /* Set new console title if appropriate. */
733
734 if (display_title && !dynamically_loaded)
735 {
736 char *cp = __progname;
737 if (strip_title_path)
738 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
739 if (isdirsep (*ptr))
740 cp = ptr + 1;
741 set_console_title (cp);
742 }
743
2eb392bd
CF
744 cygwin_finished_initializing = 1;
745 /* Call init of loaded dlls. */
746 dlls.init ();
1fd5e000 747
14a3bc2f 748 /* Execute any specified "premain" functions */
737a86d3 749 if (user_data->premain[PREMAIN_LEN / 2])
14a3bc2f 750 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
95a8465b 751 user_data->premain[i] (__argc, __argv, user_data);
14a3bc2f
CF
752
753 debug_printf ("user_data->main %p", user_data->main);
2eb392bd 754
5bc584ba
CF
755 if (dynamically_loaded)
756 {
757 set_errno (0);
758 return;
759 }
760
6ccb6bcf
CF
761 /* Disable case-insensitive globbing */
762 ignore_case_with_glob = FALSE;
763
5bc584ba
CF
764 /* Flush signals and ensure that signal thread is up and running. Can't
765 do this for noncygwin case since the signal thread is blocked due to
766 LoadLibrary serialization. */
3cb62bd6 767 wait_for_sigthread ();
5bc584ba 768
2eb392bd
CF
769 set_errno (0);
770
b0e82b74 771 MALLOC_CHECK;
166b2571 772 cygbench (__progname);
64b30629 773 if (user_data->main)
b0e82b74 774 exit (user_data->main (__argc, __argv, *user_data->envptr));
1fd5e000
CF
775}
776
c03dba93
CF
777#ifdef DEBUGGING
778void
779break_here ()
780{
781 debug_printf ("break here");
782}
783#endif
784
57013c31
CF
785void
786initial_env ()
787{
c03dba93 788 DWORD len;
57013c31
CF
789 char buf[MAX_PATH + 1];
790#ifdef DEBUGGING
791 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
792 {
6d8bd861 793 DWORD ms = atoi (buf);
c03dba93
CF
794 buf[0] = '\0';
795 len = GetModuleFileName (NULL, buf, MAX_PATH);
6d8bd861
CF
796 console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
797 Sleep (ms);
57013c31 798 }
c03dba93
CF
799 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
800 {
801 char buf1[MAX_PATH + 1];
802 len = GetModuleFileName (NULL, buf1, MAX_PATH);
56a42791
CF
803 strlwr (buf1);
804 strlwr (buf);
c03dba93
CF
805 char *p = strchr (buf, '=');
806 if (!p)
3d0ba393 807 p = (char *) "gdb.exe -nw";
c03dba93
CF
808 else
809 *p++ = '\0';
810 if (strstr (buf1, buf))
811 {
812 error_start_init (p);
813 try_to_debug ();
814 break_here ();
815 }
816 }
57013c31
CF
817#endif
818
819 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
820 {
821 _cygwin_testing = 1;
57013c31
CF
822 if ((len = GetModuleFileName (cygwin_hmodule, buf, MAX_PATH))
823 && len > sizeof ("new-cygwin1.dll")
824 && strcasematch (buf + len - sizeof ("new-cygwin1.dll"),
825 "\\new-cygwin1.dll"))
826 _cygwin_testing_magic = 0x10;
827 }
828}
829
1fd5e000
CF
830/* Wrap the real one, otherwise gdb gets confused about
831 two symbols with the same name, but different addresses.
832
833 UPTR is a pointer to global data that lives on the libc side of the
834 line [if one distinguishes the application from the dll]. */
835
72f8054f
CF
836extern "C" void __stdcall
837_dll_crt0 ()
1fd5e000 838{
4d029f39 839 DECLARE_TLS_STORAGE;
57013c31 840 initial_env ();
a4785603 841 char zeros[sizeof (fork_info->zero)] = {0};
6ea3e429 842 static NO_COPY STARTUPINFO si;
a4785603
CF
843#ifdef DEBUGGING
844 strace.microseconds ();
845#endif
846
2eb392bd 847 main_environ = user_data->envptr;
a4785603 848 *main_environ = NULL;
1fd5e000 849
c0a8e8d0 850 early_stuff_init ();
1fd5e000
CF
851 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
852 GetCurrentProcess (), &hMainProc, 0, FALSE,
853 DUPLICATE_SAME_ACCESS))
854 hMainProc = GetCurrentProcess ();
855
856 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
74509af2 857 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
1fd5e000
CF
858
859 GetStartupInfo (&si);
6ea3e429 860 child_proc_info = (child_info *) si.lpReserved2;
8698edb8
CF
861 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info
862 || memcmp (child_proc_info->zero, zeros, sizeof (zeros)) != 0)
863 child_proc_info = NULL;
864 else
1fd5e000 865 {
6ea3e429
CF
866 if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
867 multiple_cygwin_problem ("proc", child_proc_info->intro, 0);
868 else if (child_proc_info->intro == PROC_MAGIC_GENERIC
869 && child_proc_info->magic != CHILD_INFO_MAGIC)
6d8bd861
CF
870 multiple_cygwin_problem ("proc", child_proc_info->magic,
871 CHILD_INFO_MAGIC);
872 else if (child_proc_info->cygheap != (void *) &_cygheap_start)
873 multiple_cygwin_problem ("cygheap", (DWORD) child_proc_info->cygheap,
874 (DWORD) &_cygheap_start);
aaf219f0 875 unsigned should_be_cb = 0;
6ea3e429 876 switch (child_proc_info->type)
1fd5e000 877 {
57013c31 878 case _PROC_FORK:
6ea3e429 879 user_data->forkee = child_proc_info->cygpid;
aaf219f0 880 should_be_cb = sizeof (child_info_fork);
5daa0835 881 /* fall through */;
57013c31 882 case _PROC_SPAWN:
57013c31 883 case _PROC_EXEC:
aaf219f0
CF
884 if (!should_be_cb)
885 should_be_cb = sizeof (child_info);
6ea3e429
CF
886 if (should_be_cb != child_proc_info->cb)
887 multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb);
888 else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb)
889 multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union));
aaf219f0
CF
890 else
891 {
aaf219f0
CF
892 cygwin_mount_h = child_proc_info->mount_h;
893 mypid = child_proc_info->cygpid;
894 break;
895 }
1fd5e000 896 default:
6ea3e429 897 system_printf ("unknown exec type %d", child_proc_info->type);
6d8bd861
CF
898 /* intentionally fall through */
899 case _PROC_WHOOPS:
6ea3e429 900 child_proc_info = NULL;
c08e6c44 901 break;
1fd5e000
CF
902 }
903 }
904 dll_crt0_1 ();
905}
906
14a3bc2f
CF
907void
908dll_crt0 (per_process *uptr)
909{
4d029f39 910 DECLARE_TLS_STORAGE;
14a3bc2f 911 /* Set the local copy of the pointer into the user space. */
2eb392bd 912 if (uptr && uptr != user_data)
737a86d3
CF
913 {
914 memcpy (user_data, uptr, per_process_overwrite);
915 *(user_data->impure_ptr_ptr) = &reent_data;
916 }
72f8054f 917 _dll_crt0 ();
14a3bc2f
CF
918}
919
48b87053 920/* This must be called by anyone who uses LoadLibrary to load cygwin1.dll */
737a86d3 921extern "C" void
48b87053
DD
922cygwin_dll_init ()
923{
48b87053
DD
924 static char **envp;
925 static int _fmode;
48b87053
DD
926
927 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
928 GetCurrentProcess (), &hMainProc, 0, FALSE,
929 DUPLICATE_SAME_ACCESS))
930 hMainProc = GetCurrentProcess ();
931
932 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
933 &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
48b87053
DD
934 user_data->magic_biscuit = sizeof (per_process);
935
48b87053
DD
936 user_data->envptr = &envp;
937 user_data->fmode_ptr = &_fmode;
938
48b87053
DD
939 dll_crt0_1 ();
940}
941
1fd5e000
CF
942extern "C" void
943__main (void)
944{
945 do_global_ctors (user_data->ctors, FALSE);
946}
947
948enum
949 {
950 ES_SIGNAL = 1,
951 ES_CLOSEALL = 2,
952 ES_SIGPROCTERMINATE = 3
953 };
954
955extern "C" void __stdcall
956do_exit (int status)
957{
1fd5e000
CF
958 UINT n = (UINT) status;
959 static int NO_COPY exit_state = 0;
960
961 syscall_printf ("do_exit (%d)", n);
962
963 vfork_save *vf = vfork_storage.val ();
964 if (vf != NULL && vf->pid < 0)
8dca9e23 965 vf->restore_exit (status);
1fd5e000
CF
966
967 if (exit_state < ES_SIGNAL)
968 {
969 exit_state = ES_SIGNAL;
970 if (!(n & EXIT_REPARENTING))
971 {
972 signal (SIGCHLD, SIG_IGN);
973 signal (SIGHUP, SIG_IGN);
974 signal (SIGINT, SIG_IGN);
975 signal (SIGQUIT, SIG_IGN);
976 }
977 }
978
166b2571 979 if (exit_state < ES_CLOSEALL)
1fd5e000
CF
980 {
981 exit_state = ES_CLOSEALL;
982 close_all_files ();
983 }
984
985 if (exit_state < ES_SIGPROCTERMINATE)
986 {
987 exit_state = ES_SIGPROCTERMINATE;
988 sigproc_terminate ();
989 }
990
991 if (n & EXIT_REPARENTING)
aece55b9 992 n &= ~EXIT_REPARENTING;
1fd5e000
CF
993 else
994 {
995 myself->stopsig = 0;
996
997 /* restore console title */
998 if (old_title && display_title)
999 set_console_title (old_title);
1000
1001 /* Kill orphaned children on group leader exit */
f8f9b12e 1002 if (myself->has_pgid_children && myself->pid == myself->pgid)
1fd5e000
CF
1003 {
1004 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1005 myself->pid, myself->pgid);
1006 kill_pgrp (myself->pgid, -SIGHUP);
1007 }
1008
1009 /* Kill the foreground process group on session leader exit */
b98ebf54 1010 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1fd5e000
CF
1011 {
1012 tty *tp = cygwin_shared->tty[myself->ctty];
1013 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1014 myself->pid, myself->sid);
1015
45a7e957 1016 /* CGF FIXME: This can't be right. */
1fd5e000 1017 if (tp->getsid () == myself->sid)
083abe54 1018 tp->kill_pgrp (SIGHUP);
1fd5e000 1019 }
ec300c99 1020
1fd5e000 1021 tty_terminate ();
1fd5e000
CF
1022 }
1023
1024 window_terminate ();
1fd5e000 1025 events_terminate ();
1fd5e000 1026 shared_terminate ();
aea1f301 1027 cygthread::terminate ();
1fd5e000 1028
1fd5e000 1029 minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
1dc16fc7 1030 myself->exit (n);
1fd5e000
CF
1031}
1032
1033extern "C" void
1034_exit (int n)
1035{
1036 do_exit ((DWORD) n & 0xffff);
1037}
1038
1039extern "C" void
1040__api_fatal (const char *fmt, ...)
1041{
1042 char buf[4096];
1043 va_list ap;
1044
1045 va_start (ap, fmt);
1046 __small_vsprintf (buf, fmt, ap);
1047 va_end (ap);
ec300c99
CF
1048 strcat (buf, "\n");
1049 int len = strlen (buf);
1050 DWORD done;
1051 (void) WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, len, &done, 0);
1052
1053 /* Make sure that the message shows up on the screen, too, since this is
1054 a serious error. */
1055 if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)
1056 {
580e99a1
CF
1057 HANDLE h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
1058 FILE_SHARE_WRITE | FILE_SHARE_WRITE,
1059 &sec_none, OPEN_EXISTING, 0, 0);
1060 if (h != INVALID_HANDLE_VALUE)
ec300c99
CF
1061 (void) WriteFile (h, buf, len, &done, 0);
1062 }
1fd5e000
CF
1063
1064 /* We are going down without mercy. Make sure we reset
1065 our process_state. */
737a86d3 1066 sigproc_terminate ();
1fd5e000
CF
1067#ifdef DEBUGGING
1068 (void) try_to_debug ();
1069#endif
1dc16fc7 1070 myself->exit (1);
1fd5e000
CF
1071}
1072
d3fee5ec 1073void
77f4a250 1074multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
d3fee5ec 1075{
6d8bd861 1076 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
aaf219f0 1077 {
6d8bd861 1078 child_proc_info->type = _PROC_WHOOPS;
aaf219f0
CF
1079 return;
1080 }
5daa0835
CF
1081
1082 char buf[1024];
1083 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
1084 return;
1085
1086 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1087 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1088 else
77f4a250 1089 api_fatal ("%s version mismatch detected - %p/%p.\n\
d3fee5ec
CF
1090You have multiple copies of cygwin1.dll on your system.\n\
1091Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
77f4a250
CF
1092and delete all but the most recent version. The most recent version *should*\n\
1093reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1094installed the cygwin distribution.", what, magic_version, version);
d3fee5ec
CF
1095}
1096
166b2571
CF
1097#ifdef DEBUGGING
1098void __stdcall
1099cygbench (const char *s)
1100{
1101 char buf[1024];
1102 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1103 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1104}
1105#endif
This page took 0.24302 seconds and 5 git commands to generate.