⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcrt0.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* dcrt0.cc -- essentially the main() for the Cygwin dll   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license.  Please consult the file "CYGWIN_LICENSE" fordetails. */#include "winsup.h"#include <unistd.h>#include <stdlib.h>#include "glob.h"#include "exceptions.h"#include <ctype.h>#include <limits.h>#include <wingdi.h>#include <winuser.h>#include <errno.h>#include "sigproc.h"#include "pinfo.h"#include "cygerrno.h"#define NEED_VFORK#include "perprocess.h"#include "security.h"#include "fhandler.h"#include "path.h"#include "dtable.h"#include "cygheap.h"#include "child_info_magic.h"#include "perthread.h"#include "shared_info.h"#include "cygwin_version.h"#include "dll_init.h"#include "cygthread.h"#define MAX_AT_FILE_LEVEL 10#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))HANDLE NO_COPY hMainProc;HANDLE NO_COPY hMainThread;sigthread NO_COPY mainthread;		// ID of the main threadper_thread_waitq NO_COPY waitq_storage;per_thread_vfork NO_COPY vfork_storage;per_thread_signal_dispatch NO_COPY signal_dispatch_storage;per_thread NO_COPY *threadstuff[] = {&waitq_storage,				     &vfork_storage,				     &signal_dispatch_storage,				     NULL};BOOL display_title;BOOL strip_title_path;BOOL allow_glob = TRUE;codepage_type current_codepage = ansi_cp;int cygwin_finished_initializing;/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.   This is subtracted from the signal number prior to shifting the bit.   In older versions of cygwin, the signal was used as-is to shift the   bit for masking.  So, we'll temporarily detect this and set it to zero   for programs that are linked using older cygwins.  This is just a stopgap   measure to allow an orderly transfer to the new, correct sigmask method. */unsigned NO_COPY int signal_shift_subtract = 1;ResourceLocks _reslock NO_COPY;MTinterface _mtinterf;bool NO_COPY _cygwin_testing;unsigned NO_COPY _cygwin_testing_magic;char NO_COPY almost_null[1];extern "C"{  /* This is an exported copy of environ which can be used by DLLs     which use cygwin.dll.  */  char **__cygwin_environ;  char ***main_environ;  /* __progname used in getopt error message */  char *__progname;  struct _reent reent_data = _REENT_INIT(reent_data);  struct per_process __cygwin_user_data =  {/* initial_sp */ 0, /* magic_biscuit */ 0,   /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,   /* dll_major */ CYGWIN_VERSION_DLL_MINOR,   /* impure_ptr_ptr */ NULL, /* envptr */ NULL,   /* malloc */ malloc, /* free */ free,   /* realloc */ realloc,   /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,   /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,   /* bss_start */ NULL, /* bss_end */ NULL,   /* calloc */ calloc,   /* premain */ {NULL, NULL, NULL, NULL},   /* run_ctors_p */ 0,   /* unused */ {0, 0, 0, 0, 0, 0, 0},   /* forkee */ 0,   /* hmodule */ NULL,   /* api_major */ CYGWIN_VERSION_API_MAJOR,   /* api_minor */ CYGWIN_VERSION_API_MINOR,   /* unused2 */ {0, 0, 0, 0, 0},   /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,   /* impure_ptr */ &reent_data,  };  bool ignore_case_with_glob;  int __declspec (dllexport) _check_for_executable = TRUE;#ifdef DEBUGGING  int pinger;#endif};char *old_title;char title_buf[TITLESIZE + 1];static voiddo_global_dtors (void){  if (user_data->dtors)    {      void (**pfunc)() = user_data->dtors;      while (*++pfunc)	(*pfunc) ();    }}static void __stdcalldo_global_ctors (void (**in_pfunc)(), int force){  if (!force)    {      if (user_data->forkee || user_data->run_ctors_p)	return;		// inherit constructed stuff from parent pid      user_data->run_ctors_p = 1;    }  /* Run ctors backwards, so skip the first entry and find how many     there are, then run them. */  void (**pfunc)() = in_pfunc;  while (*++pfunc)    ;  while (--pfunc > in_pfunc)    (*pfunc) ();  if (user_data->magic_biscuit == SIZEOF_PER_PROCESS)    atexit (do_global_dtors);}/* * Replaces @file in the command line with the contents of the file. * There may be multiple @file's in a single command line * A \@file is replaced with @file so that echo \@foo would print * @foo and not the contents of foo. */static int __stdcallinsert_file (char *name, char *&cmd){  HANDLE f;  DWORD size;  f = CreateFile (name + 1,		  GENERIC_READ,		 /* open for reading	*/		  FILE_SHARE_READ,       /* share for reading	*/		  &sec_none_nih,	 /* no security		*/		  OPEN_EXISTING,	 /* existing file only	*/		  FILE_ATTRIBUTE_NORMAL, /* normal file		*/		  NULL);		 /* no attr. template	*/  if (f == INVALID_HANDLE_VALUE)    {      debug_printf ("couldn't open file '%s', %E", name);      return FALSE;    }  /* This only supports files up to about 4 billion bytes in     size.  I am making the bold assumption that this is big     enough for this feature */  size = GetFileSize (f, NULL);  if (size == 0xFFFFFFFF)    {      debug_printf ("couldn't get file size for '%s', %E", name);      return FALSE;    }  int new_size = strlen (cmd) + size + 2;  char *tmp = (char *) malloc (new_size);  if (!tmp)    {      debug_printf ("malloc failed, %E");      return FALSE;    }  /* realloc passed as it should */  DWORD rf_read;  BOOL rf_result;  rf_result = ReadFile (f, tmp, size, &rf_read, NULL);  CloseHandle (f);  if (!rf_result || (rf_read != size))    {      debug_printf ("ReadFile failed, %E");      return FALSE;    }  tmp[size++] = ' ';  strcpy (tmp + size, cmd);  cmd = tmp;  return TRUE;}static inline intisquote (char c){  char ch = c;  return ch == '"' || ch == '\'';}/* Step over a run of characters delimited by quotes */static /*__inline*/ char *quoted (char *cmd, int winshell){  char *p;  char quote = *cmd;  if (!winshell)    {      char *p;      strcpy (cmd, cmd + 1);      if ((p = strchr (cmd, quote)) != NULL)	strcpy (p, p + 1);      else	p = strchr (cmd, '\0');      return p;    }  const char *s = quote == '\'' ? "'" : "\\\"";  /* This must have been run from a Windows shell, so preserve     quotes for globify to play with later. */  while (*cmd && *++cmd)    if ((p = strpbrk (cmd, s)) == NULL)      {	cmd = strchr (cmd, '\0');	// no closing quote	break;      }    else if (*p == '\\')      cmd = ++p;    else if (quote == '"' && p[1] == '"')      {	*p = '\\';	cmd = ++p;			// a quoted quote      }    else      {	cmd = p + 1;		// point to after end	break;      }  return cmd;}/* Perform a glob on word if it contains wildcard characters.   Also quote every character between quotes to force glob to   treat the characters literally. */static int __stdcallglobify (char *word, char **&argv, int &argc, int &argvlen){  if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)    return 0;  int n = 0;  char *p, *s;  int dos_spec = isdrive (word);  if (!dos_spec && isquote (*word) && word[1] && word[2])    dos_spec = isdrive (word + 1);  /* We'll need more space if there are quoting characters in     word.  If that is the case, doubling the size of the     string should provide more than enough space. */  if (strpbrk (word, "'\""))    n = strlen (word);  char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];  /* Fill pattern with characters from word, quoting any     characters found within quotes. */  for (p = pattern, s = word; *s != '\000'; s++, p++)    if (!isquote (*s))      {	if (dos_spec && *s == '\\')	  *p++ = '\\';	*p = *s;      }    else      {	char quote = *s;	while (*++s && *s != quote)	  {	    if (dos_spec || *s != '\\')	      /* nothing */;	    else if (s[1] == quote || s[1] == '\\')	      s++;	    *p++ = '\\';	    *p++ = *s;	  }	if (*s == quote)	  p--;	if (*s == '\0')	    break;      }  *p = '\0';  glob_t gl;  gl.gl_offs = 0;  /* Attempt to match the argument.  Return just word (minus quoting) if no match. */  if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)    return 0;  /* Allocate enough space in argv for the matched filenames. */  n = argc;  if ((argc += gl.gl_pathc) > argvlen)    {      argvlen = argc + 10;      argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));    }  /* Copy the matched filenames to argv. */  char **gv = gl.gl_pathv;  char **av = argv + n;  while (*gv)    {      debug_printf ("argv[%d] = '%s'", n++, *gv);      *av++ = *gv++;    }  /* Clean up after glob. */  free (gl.gl_pathv);  return 1;}/* Build argv, argc from string passed from Windows.  */static void __stdcallbuild_argv (char *cmd, char **&argv, int &argc, int winshell){  int argvlen = 0;  int nesting = 0;		// monitor "nesting" from insert_file  argc = 0;  argvlen = 0;  argv = NULL;  /* Scan command line until there is nothing left. */  while (*cmd)    {      /* Ignore spaces */      if (issep (*cmd))	{	  cmd++;	  continue;	}      /* Found the beginning of an argument. */      char *word = cmd;      char *sawquote = NULL;      while (*cmd)	{	  if (*cmd != '"' && (!winshell || *cmd != '\''))	    cmd++;		// Skip over this character	  else	    /* Skip over characters until the closing quote */	    {	      sawquote = cmd;	      cmd = quoted (cmd, winshell && argc > 0);	    }	  if (issep (*cmd))	// End of argument if space	    break;	}      if (*cmd)	*cmd++ = '\0';		// Terminate `word'      /* Possibly look for @file construction assuming that this isn't	 the very first argument and the @ wasn't quoted */      if (argc && sawquote != word && *word == '@')	{	  if (++nesting > MAX_AT_FILE_LEVEL)	    api_fatal ("Too many levels of nesting for %s", word);	  if (insert_file (word, cmd))	      continue;			// There's new stuff in cmd now	}      /* See if we need to allocate more space for argv */      if (argc >= argvlen)	{	  argvlen = argc + 10;	  argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));	}      /* Add word to argv file after (optional) wildcard expansion. */      if (!winshell || !argc || !globify (word, argv, argc, argvlen))	{	  debug_printf ("argv[%d] = '%s'", argc, word);	  argv[argc++] = word;	}    }  argv[argc] = NULL;  debug_printf ("argc %d", argc);}/* sanity and sync check */void __stdcallcheck_sanity_and_sync (per_process *p){  /* Sanity check to make sure developers didn't change the per_process    */  /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */  /* about changing it].						   */  if (sizeof (per_process) != SIZEOF_PER_PROCESS)    {      api_fatal ("per_process sanity check failed");    }  /* Make sure that the app and the dll are in sync. */  /* Complain if older than last incompatible change */  if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)    api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",	       p->dll_major, CYGWIN_VERSION_DLL_EPOCH);  /* magic_biscuit != 0 if using the old style version numbering scheme.  */  if (p->magic_biscuit != SIZEOF_PER_PROCESS)    api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",	       p->magic_biscuit, SIZEOF_PER_PROCESS);  /* Complain if incompatible API changes made */  if (p->api_major != cygwin_version.api_major)    api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d < %d",	       p->api_major, cygwin_version.api_major);  if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=      CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)    signal_shift_subtract = 0;}child_info NO_COPY *child_proc_info = NULL;static MEMORY_BASIC_INFORMATION NO_COPY sm;#define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \		     PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)// __inline__ voidextern voidalloc_stack_hard_way (child_info_fork *ci, volatile char *b){  void *new_stack_pointer;  MEMORY_BASIC_INFORMATION m;  void *newbase;  int newlen;  LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;  bool noguard;  if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)    {      newbase = curbot;      newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;      noguard = 1;    }  else    {      newbase = ci->stacktop;      newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;      noguard = 0;    }  if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))    api_fatal ("fork: can't reserve memory for stack %p - %p, %E",		ci->stacktop, ci->stackbottom);  new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);  if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,		     PAGE_EXECUTE_READWRITE))    api_fatal ("fork: can't commit memory for stack %p(%d), %E",	       new_stack_pointer, ci->stacksize);  if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))    api_fatal ("fork: couldn't get new stack info, %E");  if (!noguard)    {      m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);      if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,			 CYGWIN_GUARD))	api_fatal ("fork: couldn't allocate new stack guard page %p, %E",		   m.BaseAddress);    }  if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))    api_fatal ("fork: couldn't get new stack info, %E");  ci->stacktop = m.BaseAddress;  *b = 0;}/* extend the stack prior to fork longjmp */static voidalloc_stack (child_info_fork *ci){  /* FIXME: adding 16384 seems to avoid a stack copy problem during     fork on Win95, but I don't know exactly why yet. DJ */  volatile char b[ci->stacksize + 16384];  if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))    api_fatal ("fork: couldn't get stack info, %E");  if (sm.AllocationBase != ci->stacktop)    alloc_stack_hard_way (ci, b + sizeof (b) - 1);  else    ci->stacksize = 0;  return;}static NO_COPY int mypid = 0;int _declspec(dllexport) __argc;char _declspec(dllexport) **__argv;vfork_save NO_COPY *main_vfork = NULL;voidsigthread::init (const char *s){  InitializeCriticalSection (&lock);  id = GetCurrentThreadId ();}/* Take over from libc's crt0.o and start the application. Note the   various special cases when Cygwin DLL is being runtime loaded (as   opposed to being link-time loaded by Cygwin apps) from a non   cygwin app via LoadLibrary.  */static voiddll_crt0_1 (){  /* According to onno@stack.urc.tue.nl, the exception handler record must     be on the stack.  */  /* FIXME: Verify forked children get their exception handler set up ok. */  exception_list cygwin_except_entry;  /* Initialize SIGSEGV handling, etc. */  init_exceptions (&cygwin_except_entry);  /* Set the os_being_run global. */  wincap.init ();  check_sanity_and_sync (user_data);  do_global_ctors (&__CTOR_LIST__, 1);  /* Nasty static stuff needed by newlib -- point to a local copy of     the reent stuff.     Note: this MUST be done here (before the forkee code) as the     fork copy code doesn't copy the data in libccrt0.cc (that's why we     pass in the per_process struct into the .dll from libccrt0). */  _impure_ptr = &reent_data;  user_data->resourcelocks->Init ();  user_data->threadinterface->Init (user_data->forkee);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -