Advertisement
cgrunwald

Untitled

Oct 15th, 2012
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.55 KB | None | 0 0
  1. /*$Header: /p/tcsh/cvsroot/tcsh/win32/fork.c,v 1.11 2008/08/31 14:09:01 amold Exp $*/
  2. /*-
  3.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. Neither the name of the University nor the names of its contributors
  15.  *    may be used to endorse or promote products derived from this software
  16.  *    without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28.  * SUCH DAMAGE.
  29.  */
  30.  
  31. /*
  32.  * The fork() here is based on the ideas used by cygwin
  33.  * -amol
  34.  *
  35.  */
  36.  
  37. /*
  38.  * _M_ALPHA changes by Mark Tucker
  39.  */
  40. #ifdef BUFSIZE
  41. # if       BUFSIZE < 4096
  42. #  undef   BUFSIZE
  43. #  define  BUFSIZE  4096    /* buffer size should be no less than this */
  44. # endif
  45. #else
  46. # define   BUFSIZE  4096
  47. #endif /* BUFSIZE */
  48. #define FORKSLEEP   10  /* delay loop on non-interactive fork failure */
  49. #define MAILINTVL   600 /* 10 minutes */
  50. #ifndef INBUFSIZE
  51. # define INBUFSIZE    2*BUFSIZE /* Num input characters on the command line */
  52. #endif /* INBUFSIZE */
  53. #define WIN32_LEAN_AND_MEAN
  54. #include <windows.h>
  55. #include <fcntl.h>
  56. #include <io.h>
  57. #include <stdlib.h>
  58. #include <setjmp.h>
  59. #include <ntport.h>
  60. #include "forkdata.h"
  61. //#include "sh.h"
  62.  
  63. #pragma intrinsic("memcpy", "memset","memcmp")
  64. #pragma warning(push,3) // forget about W4 here
  65.  
  66. typedef unsigned long u_long;
  67. typedef void *ptr_t;
  68. typedef unsigned char U_char;  
  69. typedef unsigned int U_int;
  70. typedef unsigned short U_short;
  71. typedef unsigned long U_long;
  72.  
  73.  
  74. static void stack_probe(void *ptr) ;
  75. /*static void heap_init(void);*/
  76. BOOL CreateWow64Events(DWORD , HANDLE *, HANDLE *, BOOL);
  77.  
  78. //
  79. // This is exported from the user program.
  80. // It must return 0 for no error !!!!
  81. extern int fork_copy_user_mem(HANDLE );
  82.  
  83. /*
  84.  * Apparently , visual c++ on the alpha does not place the
  85.  * fork data contiguously. To work around that, Mark created
  86.  * this structure (see forkdata.h)
  87.  * -amol
  88.  */
  89. ForkData gForkData = {0,0,0,0,0,{0},0,0,0};
  90.  
  91.  
  92. #ifdef _M_IX86
  93.  
  94. u_long _old_exr = 0; // Saved exception registration for longjmp
  95.  
  96. #endif // _M_ALPHA
  97. /*
  98.  * This hack is an attempt at getting to the exception registration
  99.  * in an architecture-independent way. It's critical for longjmp in a
  100.  * code using __try/__except blocks. Microsoft Visual C++ does a global
  101.  * unwind during a longjmp, and that can cause havoc if the exception
  102.  * registration stored in longjmp is lower(address wise, indicating a jump
  103.  * from below of the stack upward.) in the stack than the current
  104.  * registration (returned by NtCurrentTeb).
  105.  *
  106.  * This works with VC++, because that's all I have. With other compilers,
  107.  * there might be minimal changes required, depending on where the
  108.  * exception registration record is stored in the longjmp structure.
  109.  *
  110.  * -amol 2/6/97
  111.  */
  112.  
  113. NT_TIB * (* myNtCurrentTeb)(void);
  114.  
  115. #define GETEXCEPTIONREGIST() (((NT_TIB*)get_teb())->ExceptionList)
  116. #define GETSTACKBASE()       (((NT_TIB*)get_teb())->StackBase)
  117.  
  118.  
  119.  
  120. static NT_TIB *the_tib;
  121.  
  122. #if !defined(_M_IA64) && !defined(_M_AMD64)
  123. void *get_teb(void) {
  124.  
  125.  
  126.     if (the_tib)
  127.         return the_tib;
  128.  
  129.     myNtCurrentTeb = (void*)GetProcAddress(LoadLibrary("ntdll.dll"),
  130.                             "NtCurrentTeb");
  131.     if (!myNtCurrentTeb)
  132.         return NULL;
  133.     the_tib = myNtCurrentTeb();
  134.  
  135.     if (the_tib == NULL)
  136.         abort();
  137.     return the_tib;
  138. }
  139. #else
  140. #define get_teb NtCurrentTeb
  141. #endif _M_IA64
  142.  
  143. void set_stackbase(void*ptr){
  144.     GETSTACKBASE() = ptr;
  145. }
  146. /*
  147.  * This must be called by the application as the first thing it does.
  148.  * -amol 2/6/97
  149.  *
  150.  * Well, maybe not the FIRST..
  151.  * -amol 11/10/97
  152.  */
  153.  
  154. extern BOOL bIsWow64Process;
  155.  
  156. int fork_init(void) {
  157.  
  158.  
  159.     //heap_init(); Now called as the very first thing in silly_entry().
  160.  
  161.     if (__forked) {
  162.  
  163.  
  164.         // stack_probe probes out a decent-sized stack for the child,
  165.         // since initially it has a very small stack (1 page).
  166.         //
  167.  
  168.         /* not needed since default commit is set to 0.5MB in
  169.          * makefile.win32
  170.          *
  171.          * stack_probe((char *)__fork_stack_end - 64);
  172.          */
  173.  
  174.         //
  175.         // Save the old Exception registration record and jump
  176.         // off the cliff.
  177.         //
  178. #ifdef  _M_IX86
  179.         _old_exr = __fork_context[6];
  180.         __fork_context[6] =(int)GETEXCEPTIONREGIST();//tmp;
  181. #endif  _M_ALPHA
  182.         //
  183.         // Whee !
  184.         longjmp(__fork_context,1);
  185.     }
  186.  
  187.     return 0;
  188. }
  189. int fork(void) {
  190.  
  191.     size_t rc;
  192.     size_t stacksize;
  193.     char modname[512];/*FIXBUF*/
  194.     HANDLE  hProc,hThread, hArray[2];
  195.     STARTUPINFO si;
  196.     PROCESS_INFORMATION pi;
  197.     SECURITY_ATTRIBUTES sa;
  198.     DWORD dwCreationflags;
  199.     unsigned int priority;
  200.     HANDLE h64Parent,h64Child;
  201.  
  202. #ifndef _M_ALPHA
  203.     unsigned long fork_stack_end;
  204. #endif _M_ALPHA
  205.  
  206.     __fork_stack_begin =GETSTACKBASE();
  207.  
  208. #ifndef _M_ALPHA
  209.     __fork_stack_end = &fork_stack_end;
  210. #else
  211.     __fork_stack_end = (unsigned long *)__asm("mov $sp, $0");
  212. #endif /*_M_ALPHA*/
  213.  
  214.     h64Parent = h64Child = NULL;
  215.     //
  216.     // Create two inheritable events
  217.     //
  218.     sa.nLength = sizeof(sa);
  219.     sa.lpSecurityDescriptor =0;
  220.     sa.bInheritHandle = TRUE;
  221.     if (!__hforkchild)
  222.         __hforkchild = CreateEvent(&sa,TRUE,FALSE,NULL);
  223.     if (!__hforkparent)
  224.         __hforkparent = CreateEvent(&sa,TRUE,FALSE,NULL);
  225.  
  226.     rc = setjmp(__fork_context);
  227.  
  228.     if (rc) { // child
  229. #ifdef  _M_IX86
  230.         //
  231.         // Restore old registration
  232.         // -amol 2/2/97
  233.         GETEXCEPTIONREGIST() = (struct _EXCEPTION_REGISTRATION_RECORD*)_old_exr;
  234. #endif // _M_ALPHA
  235.         SetEvent(__hforkchild);
  236.  
  237.         dprintf("Child ready to rumble\n");
  238.         if(WaitForSingleObject(__hforkparent,FORK_TIMEOUT) != WAIT_OBJECT_0)
  239.             ExitProcess(0xFFFF);
  240.  
  241.         CloseHandle(__hforkchild);
  242.         CloseHandle(__hforkparent);
  243.         __hforkchild = __hforkparent=0;
  244.  
  245.         //__asm { int 3};
  246.         restore_fds();
  247.  
  248.         STR_environ = blk2short(environ);
  249.         environ = short2blk(STR_environ);   /* So that we can free it */
  250.  
  251.         return 0;
  252.     }
  253.     copy_fds();
  254.     memset(&si,0,sizeof(si));
  255.     si.cb= sizeof(si);
  256.  
  257.     /*
  258.      * This f!@#!@% function returns the old value even if the std handles
  259.      * have been closed.
  260.      * Skip this step, since we know tcsh will do the right thing later.
  261.      *
  262.      si.hStdInput= GetStdHandle(STD_INPUT_HANDLE);
  263.      si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  264.      si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  265.      */
  266.  
  267.     if (!GetModuleFileName(GetModuleHandle(NULL),modname,512) ) {
  268.         rc = GetLastError();
  269.         return -1;
  270.     }
  271.     dwCreationflags = GetPriorityClass(GetCurrentProcess());
  272.     priority = GetThreadPriority(GetCurrentThread());
  273.     rc = CreateProcess(NULL,
  274.             modname,
  275.             NULL,
  276.             NULL,
  277.             TRUE,
  278.             CREATE_SUSPENDED | dwCreationflags,
  279.             NULL,
  280.             NULL,
  281.             &si,
  282.             &pi);
  283.     if (!rc)  {
  284.         rc = GetLastError();
  285.         return -1;
  286.     }
  287.  
  288.     ResetEvent(__hforkchild);
  289.     ResetEvent(__hforkparent);
  290.  
  291.     hProc = pi.hProcess;
  292.     hThread = pi.hThread;
  293.  
  294.  
  295.     __forked=1;
  296.     /*
  297.      * Usage of events in the wow64 case:
  298.      *
  299.      * h64Parent : initially non-signalled
  300.      * h64Child  : initially non-signalled
  301.      *
  302.      *    1. Create the events, resume the child thread.
  303.      *    2. Child opens h64Parent to see if it is a child process in wow64
  304.      *    3. Child opens and sets h64Child to tell parent it's running. (This
  305.      *       step is needed because we can't copy to a process created in the
  306.      *       suspended state on wow64.)
  307.      *    4. Copy gForkData and then set h64Parent. This tells the child
  308.      *       that the parameters in the structure are trustworthy.
  309.      *    5. Wait for h64Child so that we know the child has created the stack
  310.      *       in dynamic memory.
  311.      *
  312.      *   The rest of the fork hack should now proceed as in x86
  313.      *
  314.      */
  315.     if (bIsWow64Process) {
  316.  
  317.         // allocate the heap for the child. this can be done even when
  318.         // the child is suspended.
  319.         // avoids inexplicable allocation failures in the child.
  320.         if (VirtualAllocEx(hProc,
  321.                     __heap_base,
  322.                     __heap_size,
  323.                     MEM_RESERVE,
  324.                     PAGE_READWRITE) == NULL) {
  325.             dprintf("virtual allocex failed %d\n",GetLastError());
  326.             goto error;
  327.         }
  328.         if (VirtualAllocEx(hProc,
  329.                     __heap_base,
  330.                     __heap_size,
  331.                     MEM_COMMIT,
  332.                     PAGE_READWRITE) == NULL) {
  333.             dprintf("virtual allocex2 failed %d\n",GetLastError());
  334.             goto error;
  335.         }
  336.  
  337.         // Do NOT expect existing events
  338.         if (!CreateWow64Events(pi.dwProcessId,&h64Parent,&h64Child,FALSE)) {
  339.             goto error;
  340.         }
  341.         ResumeThread(hThread);
  342.  
  343.         // wait for the child to tell us it is running
  344.         //if (WaitForSingleObject(h64Child,FORK_TIMEOUT) != WAIT_OBJECT_0) {
  345.         //  rc = GetLastError();
  346.         //  goto error;
  347.         //}
  348.         hArray[0] = h64Child;
  349.         hArray[1] = hProc;
  350.  
  351.         if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) !=
  352.                 WAIT_OBJECT_0){
  353.  
  354.             rc = GetLastError();
  355.             goto error;
  356.         }
  357.  
  358.     }
  359.     //
  360.     // Copy all the shared data
  361.     //
  362.     if (!WriteProcessMemory(hProc,&gForkData,&gForkData,
  363.                 sizeof(ForkData),&rc)) {
  364.         goto error;
  365.     }
  366.     if (rc != sizeof(ForkData))
  367.         goto error;
  368.  
  369.     if (!bIsWow64Process) {
  370.         rc = ResumeThread(hThread);
  371.     }
  372.     // in the wow64 case, the child will be waiting  on h64parent again.
  373.     // set it, and then wait for h64child. This will mean the child has
  374.     // a stack set up at the right location.
  375.     else {
  376.         SetEvent(h64Parent);
  377.         hArray[0] = h64Child;
  378.         hArray[1] = hProc;
  379.  
  380.         if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) !=
  381.                 WAIT_OBJECT_0){
  382.  
  383.             rc = GetLastError();
  384.             goto error;
  385.         }
  386.         CloseHandle(h64Parent);
  387.         CloseHandle(h64Child);
  388.         h64Parent = h64Child = NULL;
  389.     }
  390.  
  391.     //
  392.     // Wait for the child to start and init itself.
  393.     // The timeout is so that we don't wait too long
  394.     //
  395.     hArray[0] = __hforkchild;
  396.     hArray[1] = hProc;
  397.  
  398.     if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != WAIT_OBJECT_0){
  399.  
  400.         int err = GetLastError(); // For debugging purposes
  401.         dprintf("wait failed err %d\n",err);
  402.         goto error;
  403.     }
  404.  
  405.     // Stop the child again and copy the stack and heap
  406.     //
  407.     SuspendThread(hThread);
  408.  
  409.     if (!SetThreadPriority(hThread,priority) ) {
  410.         priority =GetLastError();
  411.     }
  412.  
  413.     // stack
  414.     stacksize = (char*)__fork_stack_begin - (char*)__fork_stack_end;
  415.     if (!WriteProcessMemory(hProc,(char *)__fork_stack_end,
  416.                 (char *)__fork_stack_end,
  417.                 (u_long)stacksize,
  418.                 &rc)){
  419.         goto error;
  420.     }
  421.     //
  422.     // copy heap itself
  423.     if (!WriteProcessMemory(hProc, (void*)__heap_base,(void*)__heap_base,
  424.                 (DWORD)((char*)__heap_top-(char*)__heap_base),
  425.                 &rc)){
  426.         goto error;
  427.     }
  428.  
  429.     rc = fork_copy_user_mem(hProc);
  430.  
  431.     if(rc) {
  432.         goto error;
  433.     }
  434.  
  435.     // Release the child.
  436.     SetEvent(__hforkparent);
  437.     rc = ResumeThread(hThread);
  438.  
  439.     __forked=0;
  440.     dprintf("forked process %d\n",pi.dwProcessId);
  441.     start_sigchild_thread(hProc,pi.dwProcessId);
  442.     close_copied_fds();
  443.  
  444.     CloseHandle(hThread);
  445.     //
  446.     // return process id to parent.
  447.     return pi.dwProcessId;
  448.  
  449. error:
  450.     __forked=0;
  451.     SetEvent(__hforkparent);
  452.     ResumeThread(hThread);
  453.     CloseHandle(hProc);
  454.     CloseHandle(hThread);
  455.     if (h64Parent) {
  456.         SetEvent(h64Parent); // don't let child block forever
  457.         CloseHandle(h64Parent);
  458.     }
  459.     if (h64Child)
  460.         CloseHandle(h64Child);
  461.     return -1;
  462. }
  463. #pragma optimize("",off)
  464. // The damn optimizer will remove the recursion, resulting in an infinite
  465. // loop. -amol 4/17/97
  466. void stack_probe (void *ptr) {
  467.     char buf[1000];
  468.     int x;
  469.  
  470.     if (&x > (int *)ptr)
  471.         stack_probe(ptr);
  472.     (void)buf;
  473. }
  474. #pragma optimize("",on)
  475. //
  476. // This function basically reserves some heap space.
  477. // In the child it also commits the size committed in the parent.
  478. void heap_init(void) {
  479.  
  480.     char * temp;
  481.     int err;
  482.     if (__forked) {
  483.         temp = (char *)VirtualAlloc((void*)__heap_base,__heap_size, MEM_RESERVE,
  484.                 PAGE_READWRITE);
  485.         if (temp != (char*)__heap_base) {
  486.             if (!temp){
  487.                 err = GetLastError();
  488.                 if (bIsWow64Process)
  489.                     ExitProcess(0);
  490.                 abort();
  491.             }
  492.             else
  493.                 __heap_base = temp;
  494.         }
  495.         if (!VirtualAlloc(__heap_base,(char*)__heap_top -(char*)__heap_base,
  496.                     MEM_COMMIT,PAGE_READWRITE)){
  497.             err = GetLastError();
  498.             if (bIsWow64Process)
  499.                 ExitProcess(0);
  500.             abort();
  501.         }
  502.         temp = (char*)__heap_base;
  503.     }
  504.     else {
  505.         SYSTEM_INFO sysinfo;
  506.         GetSystemInfo(&sysinfo);
  507.         __heap_size = sysinfo.dwPageSize * 1024;
  508.         __heap_base = VirtualAlloc(0 , __heap_size,MEM_RESERVE|MEM_TOP_DOWN,
  509.                 PAGE_READWRITE);
  510.  
  511.         if (__heap_base == 0) {
  512.             abort();
  513.         }
  514.  
  515.         __heap_top = __heap_base;
  516.     }
  517.  
  518. }
  519. //
  520. // Implementation of sbrk() for the fmalloc family
  521. //
  522. void * sbrk(int delta) {
  523.  
  524.     void *retval;
  525.     void *old_top=__heap_top;
  526.     char *b = (char*)__heap_top;
  527.  
  528.     if (delta == 0)
  529.         return  __heap_top;
  530.     if (delta > 0) {
  531.  
  532.         retval =VirtualAlloc((void*)__heap_top,delta,MEM_COMMIT,PAGE_READWRITE);
  533.  
  534.         if (retval == 0 )
  535.             abort();
  536.  
  537.         b += delta;
  538.         __heap_top = (void*)b;
  539.     }
  540.     else {
  541.         retval = VirtualAlloc((void*)((char*)__heap_top - delta),
  542.                 delta,MEM_DECOMMIT, PAGE_READWRITE);
  543.  
  544.         if (retval == 0)
  545.             abort();
  546.  
  547.         b -= delta;
  548.         __heap_top = (void*)b;
  549.     }
  550.  
  551.     return (void*) old_top;
  552. }
  553. /*
  554.  * Semantics of CreateWow64Events
  555.  *
  556.  * Try to open the events even if bOpenExisting is FALSE. This will help
  557.  * us detect name duplication.
  558.  *
  559.  *       1. If OpenEvent succeeds,and bOpenExisting is FALSE,  fail.
  560.  *
  561.  *       2. If OpenEvent failed,and bOpenExisting is TRUE fail
  562.  *
  563.  *       3. else create the events anew
  564.  *
  565.  */
  566. #define TCSH_WOW64_PARENT_EVENT_NAME "tcsh-wow64-parent-event"
  567. #define TCSH_WOW64_CHILD_EVENT_NAME  "tcsh-wow64-child-event"
  568. BOOL CreateWow64Events(DWORD pid, HANDLE *hParent, HANDLE *hChild,
  569.         BOOL bOpenExisting) {
  570.  
  571.     SECURITY_ATTRIBUTES sa;
  572.     char parentname[256],childname[256];
  573.  
  574.     *hParent = *hChild = NULL;
  575.  
  576.     // make darn sure they're not inherited
  577.     sa.nLength = sizeof(sa);
  578.     sa.lpSecurityDescriptor =0;
  579.     sa.bInheritHandle = FALSE;
  580.     //
  581.  
  582. #pragma warning(disable:4995)
  583.  
  584.     // This event tells the child to hold for gForkData to be copied
  585.     wsprintfA(parentname, "Local\\%d-%s",pid, TCSH_WOW64_PARENT_EVENT_NAME);
  586.  
  587.     wsprintfA(childname, "Local\\%d-%s",pid, TCSH_WOW64_CHILD_EVENT_NAME );
  588.  
  589. #pragma warning(default:4995)
  590.  
  591.     *hParent = OpenEvent(EVENT_ALL_ACCESS,FALSE, parentname);
  592.  
  593.     if(*hParent) {
  594.         if (bOpenExisting == FALSE) { // didn't expect to be a child process
  595.             CloseHandle(*hParent);
  596.             *hParent = NULL;
  597.             return FALSE;
  598.         }
  599.  
  600.         *hChild = OpenEvent(EVENT_ALL_ACCESS,FALSE, childname);
  601.         if (!*hChild) {
  602.             CloseHandle(*hParent);
  603.             *hParent = NULL;
  604.             return FALSE;
  605.         }
  606.  
  607.         return TRUE;
  608.     }
  609.     else { //event does not exist
  610.         if (bOpenExisting == TRUE)
  611.             return FALSE;
  612.     }
  613.  
  614.     *hParent = CreateEvent(&sa,FALSE,FALSE,parentname);
  615.     if (!*hParent)
  616.         return FALSE;
  617.  
  618.  
  619.     *hChild = CreateEvent(&sa,FALSE,FALSE,childname);  
  620.     if (!*hChild){
  621.         CloseHandle(*hParent);
  622.         *hParent = NULL;
  623.         return FALSE;
  624.     }
  625.     return TRUE;
  626. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement