- Timestamp:
- Feb 28, 2009, 8:25:12 AM (16 years ago)
- Location:
- trunk/src/kash
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kash/shfile.c
r2290 r2293 451 451 } 452 452 453 #if K_OS == K_OS_WINDOWS && defined(SHFILE_IN_USE) //&& defined(SH_FORKED_MODE) 454 /** 455 * Helper for shfork. 456 * 457 * @param pfdtab The file descriptor table. 458 * @param set Whether to make all handles inheritable (1) or 459 * to restore them to the rigth state (0). 460 * @param hndls Where to store the three standard handles. 461 */ 462 void shfile_fork_win(shfdtab *pfdtab, int set, intptr_t *hndls) 463 { 464 shmtxtmp tmp; 465 unsigned i; 466 467 shmtx_enter(&pfdtab->mtx, &tmp); 468 469 i = pfdtab->size; 470 while (i-- > 0) 471 { 472 if (pfdtab->tab[i].fd == i) 473 { 474 HANDLE hFile = (HANDLE)pfdtab->tab[i].native; 475 DWORD fFlag = set || !pfdtab->tab[i].cloexec ? HANDLE_FLAG_INHERIT : 0; 476 if (!SetHandleInformation(hFile, HANDLE_FLAG_INHERIT, fFlag)) 477 { 478 DWORD err = GetLastError(); 479 assert(0); 480 } 481 } 482 } 483 484 if (hndls) 485 { 486 for (i = 0; i < 3; i++) 487 { 488 if ( pfdtab->size > i 489 && pfdtab->tab[i].fd == 0) 490 hndls[i] = pfdtab->tab[i].native; 491 else 492 hndls[i] = (intptr_t)INVALID_HANDLE_VALUE; 493 } 494 } 495 496 shmtx_leave(&pfdtab->mtx, &tmp); 497 } 498 #endif 499 500 453 501 /** 454 502 * open(). -
trunk/src/kash/shfile.h
r2290 r2293 119 119 120 120 int shfile_init(shfdtab *, shfdtab *); 121 void shfile_fork_win(shfdtab *pfdtab, int set, intptr_t *hndls); 121 122 122 123 int shfile_open(shfdtab *, const char *, unsigned, mode_t); -
trunk/src/kash/shfork-win.c
r2292 r2293 7 7 #include <locale.h> 8 8 #include "shinstance.h" 9 #include <Windows.h> 10 11 /******************************************************************************* 12 * Defined Constants And Macros * 13 *******************************************************************************/ 14 /** The stack size. This is also defined in shforkA-win.asm. */ 15 #define SHFORK_STACK_SIZE (1*1024*1024) 9 16 10 17 … … 26 33 /* called by shforkA-win.asm: */ 27 34 void *shfork_maybe_forked(int argc, char **argv, char **envp); 28 extern int shfork_body( uintptr_tstack_ptr);35 extern int shfork_body(shinstance *psh, void *stack_ptr); 29 36 30 37 … … 56 63 || strcmp(argv[6], "--stack-limit")) 57 64 { 65 char *stack; 58 66 shheap_init(); 59 return (char *)sh_malloc(NULL, 1*1024*1024) + 1*1024*1024; 67 stack = (char *)sh_malloc(NULL, SHFORK_STACK_SIZE) + SHFORK_STACK_SIZE; 68 g_stack_base = stack + SHFORK_STACK_SIZE; 69 g_stack_limit = stack; 70 return stack; 60 71 } 61 72 … … 64 75 * fork() call. 65 76 */ 66 77 setlocale(LC_ALL, ""); 67 78 68 79 /* … … 121 132 ptr <<= 4; 122 133 ptr |= digit; 134 str++; 123 135 } 124 136 return (void *)ptr; … … 132 144 * 133 145 * @returns child pid on success, -1 and errno on failure. 146 * @param psh The shell that's forking. 134 147 * @param stack_ptr The stack address at which the guest is suppost to resume. 135 148 */ 136 int shfork_body( uintptr_tstack_ptr)149 int shfork_body(shinstance *psh, void *stack_ptr) 137 150 { 138 errno = ENOSYS; 139 return -1; 151 PROCESS_INFORMATION ProcInfo; 152 STARTUPINFO StrtInfo; 153 intptr_t hndls[3]; 154 char szExeName[1024]; 155 char szCmdLine[1024+256]; 156 DWORD cch; 157 int rc = 0; 158 159 /* 160 * Mark all handles inheritable and get the three standard handles. 161 */ 162 shfile_fork_win(&psh->fdtab, 1 /* set */, &hndls[0]); 163 164 /* 165 * Create the process. 166 */ 167 cch = GetModuleFileName(GetModuleHandle(NULL), szExeName, sizeof(szExeName)); 168 if (cch > 0) 169 { 170 #if 0 /* quoting the program name doesn't seems to be working :/ */ 171 szCmdLine[0] = '"'; 172 memcpy(&szCmdLine[1], szExeName, cch); 173 szCmdLine[++cch] = '"'; 174 #else 175 memcpy(&szCmdLine[0], szExeName, cch); 176 #endif 177 cch += sprintf(&szCmdLine[cch], " --!forked!-- --stack-address %p --stack-base %p --stack-limit %p", 178 stack_ptr, g_stack_base, g_stack_limit); 179 szCmdLine[cch+1] = '\0'; 180 181 memset(&StrtInfo, '\0', sizeof(StrtInfo)); /* just in case. */ 182 StrtInfo.cb = sizeof(StrtInfo); 183 StrtInfo.lpReserved = NULL; 184 StrtInfo.lpDesktop = NULL; 185 StrtInfo.lpTitle = NULL; 186 StrtInfo.dwX = 0; 187 StrtInfo.dwY = 0; 188 StrtInfo.dwXSize = 0; 189 StrtInfo.dwYSize = 0; 190 StrtInfo.dwXCountChars = 0; 191 StrtInfo.dwYCountChars = 0; 192 StrtInfo.dwFillAttribute = 0; 193 StrtInfo.dwFlags = 0; 194 StrtInfo.wShowWindow = 0; 195 StrtInfo.cbReserved2 = 0; 196 StrtInfo.lpReserved2 = NULL; 197 StrtInfo.hStdInput = (HANDLE)hndls[0]; 198 StrtInfo.hStdOutput = (HANDLE)hndls[1]; 199 StrtInfo.hStdError = (HANDLE)hndls[2]; 200 if (CreateProcess(szExeName, 201 szCmdLine, 202 NULL, /* pProcessAttributes */ 203 NULL, /* pThreadAttributes */ 204 TRUE, /* bInheritHandles */ 205 CREATE_SUSPENDED, 206 NULL, /* pEnvironment */ 207 NULL, /* pCurrentDirectory */ 208 &StrtInfo, 209 &ProcInfo)) 210 { 211 /* 212 * Copy the memory to the child. 213 */ 214 rc = shheap_fork_copy_to_child(ProcInfo.hProcess); 215 if (!rc) 216 { 217 if (ResumeThread(ProcInfo.hThread) != (DWORD)-1) 218 { 219 rc = sh_add_child(psh, ProcInfo.dwProcessId, ProcInfo.hProcess); 220 if (!rc) 221 rc = (int)ProcInfo.dwProcessId; 222 } 223 else 224 { 225 DWORD dwErr = GetLastError(); 226 fprintf(stderr, "shfork: ResumeThread() -> %d\n", dwErr); 227 errno = EINVAL; 228 rc = -1; 229 } 230 } 231 if (rc == -1) 232 { 233 TerminateProcess(ProcInfo.hProcess, 127); 234 /* needed?: ResumeThread(ProcInfo.hThread); */ 235 CloseHandle(ProcInfo.hProcess); 236 } 237 CloseHandle(ProcInfo.hThread); 238 } 239 else 240 { 241 DWORD dwErr = GetLastError(); 242 fprintf(stderr, "shfork: CreateProcess(%s) -> %d\n", szExeName, dwErr); 243 errno = EINVAL; 244 rc = -1; 245 } 246 } 247 else 248 { 249 DWORD dwErr = GetLastError(); 250 fprintf(stderr, "shfork: GetModuleFileName() -> %d\n", dwErr); 251 errno = EINVAL; 252 rc = -1; 253 } 254 255 /* 256 * Restore the handle inherit property. 257 */ 258 shfile_fork_win(&psh->fdtab, 0 /* restore */, NULL); 259 260 return rc; 140 261 } -
trunk/src/kash/shforkA-win.asm
r2292 r2293 32 32 %define NAME(name) _ %+ name 33 33 %endif 34 35 ;; The stack size. This is also defined in shfork-win.c. 36 %define SHFORK_STACK_SIZE (1*1024*1024) 34 37 35 38 … … 108 111 mov [gs:08h], rax 109 112 .below: 110 lea r9, [rax - 1*1024*1024]113 lea r9, [rax - SHFORK_STACK_SIZE] 111 114 cmp r9, r11 112 115 ja .above … … 132 135 mov [fs:04h], rax 133 136 .below: 134 lea edx, [eax - 1*1024*1024]137 lea edx, [eax - SHFORK_STACK_SIZE] 135 138 cmp edx, ecx 136 139 ja .above … … 175 178 ;; 176 179 ; sh_fork() worker 180 ; 181 ; @returns See fork(). 182 ; @param psh 177 183 ; 178 184 NAME(shfork_do_it): … … 230 236 ; 231 237 %ifdef KBUILD_ARCH_AMD64 232 mov rcx, rsp 233 %else 234 mov ecx, esp 238 ;mov rcx, rcx ; psh 239 mov rdx, rsp ; stack_ptr 240 sub rsp, 20h 241 call NAME(shfork_body) 242 lea rsp, [rsp + 20h] 243 %else 244 mov edx, esp 245 mov ecx, [ebp + 8h] ; psh 235 246 sub esp, 20h 236 mov [esp ], ecx237 %endif 247 mov [esp ], edx 248 mov [esp + 4], ecx ; stack_ptr 238 249 call NAME(shfork_body) 239 %ifdef KBUILD_ARCH_AMD64240 250 lea esp, [esp + 20h] 241 251 %endif -
trunk/src/kash/shheap.c
r2292 r2293 137 137 #ifdef SHHEAP_IN_USE 138 138 139 # if K_OS == K_OS_WINDOWS 140 /** 141 * Copies the heap into the child process. 142 * 143 * @returns 0 on success, -1 and errno on failure. 144 * @param hChild Handle to the child process. 145 */ 146 int shheap_fork_copy_to_child(void *hChild) 147 { 148 shmemchunk *chunk; 149 shmtxtmp tmp; 150 int err = 0; 151 152 shmtx_enter(&g_sh_heap_mtx, &tmp); 153 154 for (chunk = g_sh_heap; chunk; chunk = chunk->next) 155 { 156 void *chld_chnk; 157 158 chld_chnk = (shmemchunk *)VirtualAllocEx(hChild, chunk, chunk->size, 159 MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 160 if (chld_chnk != chunk) 161 { 162 err = GetLastError(); 163 fprintf(stderr, "shfork: VirtualAllocEx(,%p,%p,) -> %d\n", chunk, chunk->size, err); 164 break; 165 } 166 167 if (!WriteProcessMemory(hChild, chunk, chunk, chunk->size, NULL /* pNumberOfBytesWritten */)) 168 { 169 err = GetLastError(); 170 fprintf(stderr, "shfork: WriteProcessMemory(,%p,,%p,) -> %d\n", chunk, chunk->size, err); 171 break; 172 } 173 } 174 175 shmtx_leave(&g_sh_heap_mtx, &tmp); 176 177 if (!err) 178 return 0; 179 errno = EINVAL; 180 return -1; 181 } 182 # endif 183 184 139 185 /** 140 186 * Checks a heap chunk. -
trunk/src/kash/shheap.h
r2292 r2293 33 33 /* heap */ 34 34 int shheap_init(void); 35 int shheap_fork_copy_to_child(void *); 36 35 37 void *sh_malloc(shinstance *, size_t); 36 38 void *sh_calloc(shinstance *, size_t, size_t); -
trunk/src/kash/shinstance.c
r2292 r2293 38 38 # include <pwd.h> 39 39 #endif 40 #if K_OS == K_OS_WINDOWS 41 # include <Windows.h> 42 #endif 40 43 #include "shinstance.h" 41 44 42 45 #if K_OS == K_OS_WINDOWS 43 extern pid_t shfork_do_it( void); /* shforkA-win.asm */46 extern pid_t shfork_do_it(shinstance *psh); /* shforkA-win.asm */ 44 47 #endif 45 48 … … 308 311 } 309 312 313 /** getenv() */ 310 314 char *sh_getenv(shinstance *psh, const char *var) 311 315 { … … 868 872 } 869 873 874 /** 875 * Adds a child to the shell 876 * 877 * @returns 0 on success, on failure -1 and errno set to ENOMEM. 878 * 879 * @param psh The shell instance. 880 * @param pid The child pid. 881 * @param hChild Windows child handle. 882 */ 883 int sh_add_child(shinstance *psh, pid_t pid, void *hChild) 884 { 885 /* get a free table entry. */ 886 int i = psh->num_children++; 887 if (!(i % 32)) 888 { 889 void *ptr = sh_realloc(psh, psh->children, sizeof(*psh->children) * (i + 32)); 890 if (!ptr) 891 { 892 psh->num_children--; 893 errno = ENOMEM; 894 return -1; 895 } 896 psh->children = ptr; 897 } 898 899 /* add it */ 900 psh->children[i].pid = pid; 901 #if K_OS == K_OS_WINDOWS 902 psh->children[i].hChild = hChild; 903 #endif 904 (void)hChild; 905 return 0; 906 } 907 870 908 pid_t sh_fork(shinstance *psh) 871 909 { … … 877 915 878 916 #elif K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE) 879 pid = shfork_do_it( );917 pid = shfork_do_it(psh); 880 918 881 919 #elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE) … … 896 934 } 897 935 936 /** waitpid() */ 898 937 pid_t sh_waitpid(shinstance *psh, pid_t pid, int *statusp, int flags) 899 938 { 900 939 pid_t pidret; 901 940 #ifdef SH_PURE_STUB_MODE 902 941 *statusp = 0; 903 #ifdef SH_PURE_STUB_MODE904 942 pidret = -1; 905 943 906 #elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE) 944 #elif K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE) 945 DWORD dwRet; 946 HANDLE hChild = INVALID_HANDLE_VALUE; 947 int i; 948 949 *statusp = 0; 950 pidret = -1; 951 if (pid != -1) 952 { 953 /* 954 * A specific child, try look it up in the child process table 955 * and wait for it. 956 */ 957 for (i = 0; i < psh->num_children; i++) 958 if (psh->children[i].pid == pid) 959 break; 960 if (i < psh->num_children) 961 { 962 dwRet = WaitForSingleObject(psh->children[i].hChild, 963 flags & WNOHANG ? 0 : INFINITE); 964 if (dwRet == WAIT_OBJECT_0) 965 hChild = psh->children[i].hChild; 966 else if (dwRet == WAIT_TIMEOUT) 967 { 968 i = -1; /* don't try close anything */ 969 pidret = 0; 970 } 971 else 972 errno = ECHILD; 973 } 974 else 975 errno = ECHILD; 976 } 977 else if (psh->num_children <= MAXIMUM_WAIT_OBJECTS) 978 { 979 HANDLE ahChildren[64]; 980 for (i = 0; i < psh->num_children; i++) 981 ahChildren[i] = psh->children[i].hChild; 982 dwRet = WaitForMultipleObjects(psh->num_children, &ahChildren[0], 983 FALSE, 984 flags & WNOHANG ? 0 : INFINITE); 985 i = dwRet - WAIT_OBJECT_0; 986 if ((unsigned)i < (unsigned)psh->num_children) 987 { 988 hChild = psh->children[i].hChild; 989 } 990 else if (dwRet == WAIT_TIMEOUT) 991 { 992 i = -1; /* don't try close anything */ 993 pidret = 0; 994 } 995 else 996 { 997 i = -1; /* don't try close anything */ 998 errno = EINVAL; 999 } 1000 } 1001 else 1002 { 1003 fprintf(stderr, "panic! too many children!\n"); 1004 i = -1; 1005 *(char *)1 = '\0'; /** @todo implement this! */ 1006 } 1007 1008 /* 1009 * Close the handle, and if we succeeded collect the exit code first. 1010 */ 1011 if ( i >= 0 1012 && i < psh->num_children) 1013 { 1014 if (hChild != INVALID_HANDLE_VALUE) 1015 { 1016 DWORD dwExitCode = 127; 1017 if (GetExitCodeProcess(hChild, &dwExitCode)) 1018 { 1019 pidret = psh->children[i].pid; 1020 if (dwExitCode && !W_EXITCODE(dwExitCode, 0)) 1021 dwExitCode |= 16; 1022 *statusp = W_EXITCODE(dwExitCode, 0); 1023 } 1024 else 1025 errno = EINVAL; 1026 } 1027 1028 /* remove and close */ 1029 hChild = psh->children[i].hChild; 1030 psh->num_children--; 1031 if (i < psh->num_children) 1032 psh->children[i] = psh->children[psh->num_children]; 1033 i = CloseHandle(hChild); assert(i); 1034 } 1035 1036 #elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE) 1037 *statusp = 0; 907 1038 # ifdef _MSC_VER 908 1039 pidret = -1; -
trunk/src/kash/shinstance.h
r2291 r2293 59 59 #endif 60 60 61 /** 62 * A child process. 63 */ 64 typedef struct shchild 65 { 66 pid_t pid; /**< The pid. */ 67 #if K_OS == K_OS_WINDOWS 68 void *hChild; /**< The process handle. */ 69 #endif 70 } shchild; 61 71 62 72 /* memalloc.c */ … … 135 145 shsigset_t sigmask; /**< Our signal mask. */ 136 146 char **shenviron; /**< The environment vector. */ 147 int num_children; /**< Number of children in the array. */ 148 shchild *children; /**< The child array. */ 137 149 138 150 /* alias.c */ … … 396 408 397 409 /* wait / process */ 410 int sh_add_child(shinstance *psh, pid_t pid, void *hChild); 398 411 #ifdef _MSC_VER 399 412 # include <process.h> -
trunk/src/kash/show.c
r2289 r2293 274 274 trputc(shinstance *psh, int c) 275 275 { 276 if ( debug(psh) != 1)276 if (psh && debug(psh) != 1) 277 277 return; 278 278 putc(c, tracefile); … … 287 287 va_list va; 288 288 289 if ( (psh || !tracefile) && debug(psh) != 1)290 return; 291 289 if (!tracefile || (psh && debug(psh) != 1)) 290 return; 291 fprintf(tracefile, "[%d] ", sh_getpid(psh)); 292 292 va_start(va, fmt); 293 293 (void) vfprintf(tracefile, fmt, va); … … 304 304 int savederrno = errno; 305 305 306 if ( (psh || !tracefile) && debug(psh) != 1)307 return; 308 306 if (!tracefile || (psh && debug(psh) != 1)) 307 return; 308 fprintf(tracefile, "[%d] ", sh_getpid(psh)); 309 309 (void) vfprintf(tracefile, fmt, va); 310 310 … … 320 320 int savederrno = errno; 321 321 322 if ( (psh || !tracefile) && debug(psh) != 1)322 if (!tracefile || (psh && debug(psh) != 1)) 323 323 return; 324 324 fputs(s, tracefile); … … 335 335 char c; 336 336 337 if ( (psh || !tracefile) && debug(psh) != 1)337 if (!tracefile || (psh && debug(psh) != 1)) 338 338 return; 339 339 putc('"', tracefile); … … 378 378 int savederrno = errno; 379 379 380 if ( (psh || !tracefile) && debug(psh) != 1)380 if (!tracefile || (psh && debug(psh) != 1)) 381 381 return; 382 382 while (*ap) { … … 400 400 int fd; 401 401 402 if ( debug(psh) != 1) {402 if (psh && debug(psh) != 1) { 403 403 if (tracefile) 404 404 fflush(tracefile);
Note:
See TracChangeset
for help on using the changeset viewer.