int nt_texec(char *prog, char**args ) { STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE htemp; DWORD type=0; DWORD dwCreationflags; unsigned int priority; char *argv0 = NULL, *savepath = NULL; char *cmdstr,*cmdend ; char *originalPtr = NULL; unsigned int cmdsize,cmdlen; char *p2; char **savedargs; int retries=0; int hasdot =0; int is_winnt=0; int retval = 1; memset(&si,0,sizeof(si)); savedargs = args; /* MUST FREE !! */ originalPtr = cmdstr= heap_alloc(MAX_PATH<<2); cmdsize = MAX_PATH<<2; is_winnt = (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS); p2 = cmdstr; cmdlen = 0; cmdlen += copy_quote_and_fix_slashes(prog,cmdstr,&hasdot); p2 += cmdlen; if (*cmdstr != '"') { // If not quoted, skip initial character we left for quote *cmdstr = 'A'; cmdstr++; cmdsize--; } *p2 = 0; cmdend = p2; if (!is_winnt) { argv0 = NULL; } else { argv0= heap_alloc(MAX_PATH); (void)StringCbPrintf(argv0,MAX_PATH,"%s",prog); } si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; htemp= (HANDLE)_get_osfhandle(SHIN); DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), &si.hStdInput,0,TRUE,DUPLICATE_SAME_ACCESS); htemp= (HANDLE)_get_osfhandle(SHOUT); DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), &si.hStdOutput,0,TRUE,DUPLICATE_SAME_ACCESS); htemp= (HANDLE)_get_osfhandle(SHDIAG); DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), &si.hStdError,0,TRUE,DUPLICATE_SAME_ACCESS); /* quotespace hack needed since execv() would have separated args, but createproces doesnt -amol 9/14/96 */ args++; // the first arg is the command dprintf("nt_texec calling c_a_a_q"); if(concat_args_and_quote(args,&originalPtr,&cmdstr,&cmdlen,&cmdend,&cmdsize) == NULL) { retval = 1; errno = ENOMEM; heap_free(originalPtr); goto free_mem; } *cmdend = 0; dwCreationflags = GetPriorityClass(GetCurrentProcess()); priority = GetThreadPriority(GetCurrentThread()); if (is_winnt) { retries = 0; // For NT, try ShellExecuteEx first do { if (GetBinaryType(argv0,&type)) break; if (GetLastError() == ERROR_BAD_EXE_FORMAT){ errno = ENOEXEC; if (!__nt_only_start_exes) try_shell_ex(savedargs,0,FALSE); if (errno) { retval = 1; goto free_mem; } else { retval = 0; goto free_mem; } } // only try shellex again after appending ".exe fails else if ( retries > 1 ){ if ( ( (argv0[0] == '\\') ||(argv0[0] == '/') ) && ( (argv0[1] == '\\') ||(argv0[1] == '/') ) && (!args[1]) ) if (!__nt_only_start_exes) try_shell_ex(savedargs,0,FALSE); errno = ENOENT; } if (retries == 0) (void)StringCbPrintf(argv0,MAX_PATH,"%s.exe",prog); else if (retries == 1) { (void)StringCbPrintf(argv0,MAX_PATH,"%s.EXE",prog); } retries++; }while(retries < 3); } savepath = fix_path_for_child(); re_cp: dprintf("nt_texec cmdstr %s\n",cmdstr); if (!CreateProcess(argv0, cmdstr, NULL, NULL, TRUE, // need this for redirecting std handles dwCreationflags, NULL,//envcrap, NULL, &si, &pi) ){ if (GetLastError() == ERROR_BAD_EXE_FORMAT) { errno = ENOEXEC; } else if (GetLastError() == ERROR_INVALID_PARAMETER) { errno = ENAMETOOLONG; }else { errno = ENOENT; } if (!is_winnt && !hasdot) { //append '.' to the end if needed StringCbCat(cmdstr,cmdsize,"."); hasdot=1; goto re_cp; } retval = 1; } else{ int gui_app ; DWORD exitcode; char guivar[50]; if (GetEnvironmentVariable("TCSH_NOASYNCGUI",guivar,50)) gui_app=0; else gui_app= is_gui(argv0); if(!gui_app) { WaitForSingleObject(pi.hProcess,INFINITE); (void)GetExitCodeProcess(pi.hProcess,&exitcode); setv(STRstatus, putn(exitcode), VAR_READWRITE);/*FIXRESET*/ } retval = 0; CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } free_mem: CloseHandle(si.hStdInput); CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); if(savepath) restore_path(savepath); heap_free(originalPtr); if (argv0) heap_free(argv0); return retval; }
void dostart(Char ** vc, struct command *c) { char *cmdstr,*cmdend,*ptr; char argv0[256];/*FIXBUF*/ DWORD cmdsize; char *currdir=NULL; char *savepath; char **v = NULL; STARTUPINFO si; PROCESS_INFORMATION pi; DWORD dwCreationFlags=CREATE_NEW_CONSOLE; DWORD k,cmdlen,j,jj,ret; UNREFERENCED_PARAMETER(c); vc++; cmdsize = 512; cmdstr = heap_alloc(cmdsize); cmdend = cmdstr; cmdlen = 0; memset(&si,0,sizeof(si)); si.cb = sizeof(si); vc = glob_all_or_error(vc); v = short2blk(vc); if(v == NULL) { stderror(ERR_NOMEM); return; } blkfree(vc); for (k = 0; v[k] != NULL ; k++){ if ( v[k][0] == '-' ) { /* various options */ if( (v[k][1] == 'T') || (v[k][1] == 't')) si.lpTitle =&( v[k][2]); else if ( (v[k][1] == 'D') || (v[k][1] == 'd')) currdir =&( v[k][2]); else if (!_stricmp(&v[k][1],"MIN") ) si.wShowWindow = SW_SHOWMINIMIZED; else if (!_stricmp(&v[k][1],"MAX") ) si.wShowWindow = SW_SHOWMAXIMIZED; else if (!_stricmp(&v[k][1],"SEPARATE") ) dwCreationFlags |= CREATE_SEPARATE_WOW_VDM; else if (!_stricmp(&v[k][1],"SHARED") ) dwCreationFlags |= CREATE_SHARED_WOW_VDM; else if (!_stricmp(&v[k][1],"LOW") ) dwCreationFlags |= IDLE_PRIORITY_CLASS; else if (!_stricmp(&v[k][1],"NORMAL") ) dwCreationFlags |= NORMAL_PRIORITY_CLASS; else if (!_stricmp(&v[k][1],"HIGH") ) dwCreationFlags |= HIGH_PRIORITY_CLASS; else if (!_stricmp(&v[k][1],"REALTIME") ) dwCreationFlags |= REALTIME_PRIORITY_CLASS; else{ blkfree((Char **)v); stderror(ERR_SYSTEM,start_usage,"See CMD.EXE for more info");/*FIXRESET*/ } } else{ // non-option arg break; } } /* * Stop the insanity of requiring start "tcsh -l" * Option processing now stops at first non-option arg * -amol 5/30/96 */ for (jj=k;v[jj] != NULL; jj++) { j=(lstrlen(v[jj]) + 2); if (j + cmdlen > cmdsize) { ptr = cmdstr; cmdstr = heap_realloc(cmdstr, max(cmdsize << 1, j+cmdlen) ); if(!cmdstr) { heap_free(ptr); stderror(ERR_NOMEM,"start");/*FIXRESET*/ } cmdend = cmdstr + (cmdend - ptr); cmdsize <<= 1; } ptr = v[jj]; while (*ptr) { *cmdend++ = *ptr++; cmdlen++; } *cmdend++ = ' '; cmdlen++; } if (jj == k) { blkfree((Char **)v); stderror(ERR_SYSTEM,start_usage,"See CMD.EXE for more info");/*FIXRESET*/ return; } *cmdend = 0; StringCbCopy(argv0,sizeof(argv0),v[k]); /* * strictly speaking, it should do no harm to set the path * back to '\'-delimited even in the parent, but in the * interest of consistency, we save the old value and restore it * later */ savepath = fix_path_for_child(); if (! CreateProcess(NULL, cmdstr, NULL, NULL, FALSE, dwCreationFlags, NULL, currdir, &si, &pi) ) { restore_path(savepath); ret = GetLastError(); if (ret == ERROR_BAD_EXE_FORMAT || ret == ERROR_ACCESS_DENIED || (ret == ERROR_FILE_NOT_FOUND && (is_url(v[k]) || is_directory(v[k])) ) ) { char erbuf[MAX_PATH]; errno = ENOEXEC; try_shell_ex(&v[k],0,FALSE); heap_free(cmdstr); /* free !! */ if (errno) { strerror_s(erbuf,sizeof(erbuf),errno); stderror(ERR_ARCH,argv0,erbuf);/*FIXRESET*/ } } else if (ret == ERROR_INVALID_PARAMETER) { errno = ENAMETOOLONG; heap_free(cmdstr); /* free !! */ stderror(ERR_TOOLARGE,argv0);/*FIXRESET*/ } else { errno = ENOENT; if ( ( (v[k][0] == '\\') ||(v[k][0] == '/') ) && ( (v[k][1] == '\\') ||(v[k][1] == '/') ) && (!v[k+1]) ) try_shell_ex(&v[k],0,FALSE); heap_free(cmdstr); /* free !! */ if (errno) { stderror(ERR_NOTFOUND,argv0);/*FIXRESET*/ } } } else { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); heap_free(cmdstr); restore_path(savepath); } blkfree((Char **)v); return; }
void nt_execve(char *prog, char**args, char**envir ) { STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE htemp; BOOL bRet; DWORD type=0; DWORD dwCreationflags; unsigned int priority; char *argv0; char *cmdstr, *cmdend ; char *originalPtr; unsigned int cmdsize,cmdlen; char *p2; char **savedargs; int retries=0; int hasdot =0; int is_winnt ; memset(&si,0,sizeof(si)); savedargs = args; /* * This memory is not freed because we are exec()ed and will * not be alive long. */ originalPtr = cmdstr= heap_alloc(MAX_PATH<<2); is_winnt = (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS); cmdsize = MAX_PATH<<2; p2 = cmdstr; cmdlen = 0; cmdlen += copy_quote_and_fix_slashes(prog,cmdstr,&hasdot); p2 += cmdlen; /* If the command was not quoted , skip initial character we left for quote */ if (*cmdstr != '"') { *cmdstr = 'A'; cmdstr++; cmdsize--; } *p2 = 0; cmdend = p2; if (!is_winnt){ argv0 = NULL; goto win95_directly_here; } else { argv0 = heap_alloc(MAX_PATH); /* not freed */ wsprintf(argv0,"%s",prog); } retry: bRet=GetBinaryType(argv0,&type); dprintf("binary type for %s is %d\n",argv0,bRet); // // For NT, append .EXE and retry // if (is_winnt && !bRet ) { /* Don't append .EXE if it could be a script file */ if (GetLastError() == ERROR_BAD_EXE_FORMAT){ errno = ENOEXEC; if (!__nt_only_start_exes) try_shell_ex(args,1,FALSE); //can't throw on error return; } else if ( retries ){ if ( ( (argv0[0] == '\\') ||(argv0[0] == '/') ) && ( (argv0[1] == '\\') ||(argv0[1] == '/') ) && (!args[1]) ) if (!__nt_only_start_exes) try_shell_ex(args,1,FALSE); errno = ENOENT; } if (retries > 1){ return; } // Try uppercase once and then lower case // if (!retries) wsprintf(argv0,"%s.exe",prog); else wsprintf(argv0,"%s.EXE",prog); /* fix for clearcase */ retries++; goto retry; } win95_directly_here: si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; htemp= (HANDLE)_get_osfhandle(0); DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), &si.hStdInput,0,TRUE,DUPLICATE_SAME_ACCESS); htemp= (HANDLE)_get_osfhandle(1); DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), &si.hStdOutput,0,TRUE,DUPLICATE_SAME_ACCESS); htemp= (HANDLE)_get_osfhandle(2); DuplicateHandle(GetCurrentProcess(),htemp,GetCurrentProcess(), &si.hStdError,0,TRUE,DUPLICATE_SAME_ACCESS); *args++; // the first arg is the command dprintf("nt_execve calling c_a_a_q"); if(!concat_args_and_quote(args,&originalPtr,&cmdstr,&cmdlen,&cmdend, &cmdsize)) { dprintf("concat_args_and_quote failed\n"); heap_free(originalPtr); errno = ENOMEM; goto fail_return; } *cmdend = 0; dwCreationflags = GetPriorityClass(GetCurrentProcess()); if (__nt_child_nohupped) { dwCreationflags |= DETACHED_PROCESS; } priority = GetThreadPriority(GetCurrentThread()); (void)fix_path_for_child(); if (is_winnt) dwCreationflags |= CREATE_SUSPENDED; re_cp: dprintf("argv0 %s cmdstr %s\n",argv0,cmdstr); bRet = CreateProcessA(argv0, cmdstr, NULL, NULL, TRUE, // need this for redirecting std handles dwCreationflags, NULL, NULL, &si, &pi); if (!bRet){ if (GetLastError() == ERROR_BAD_EXE_FORMAT) { if (!__nt_only_start_exes) try_shell_ex(savedargs,1,FALSE); errno = ENOEXEC; } else if (GetLastError() == ERROR_INVALID_PARAMETER) { /* can't get invalid parameter, so this must be * the case when we exceed the command length limit. */ errno = ENAMETOOLONG; } else { errno = ENOENT; } if (!is_winnt && !hasdot) { //append '.' to the end if needed lstrcat(cmdstr,"."); hasdot=1; goto re_cp; } } else{ int gui_app ; char guivar[50]; if (GetEnvironmentVariable("TCSH_NOASYNCGUI",guivar,50)) gui_app=0; else { if (is_winnt || hasdot) gui_app= is_gui(argv0); else gui_app = is_9x_gui(prog); } if (is_winnt && !SetThreadPriority(pi.hThread,priority) ) { priority =GetLastError(); } if (is_winnt) ResumeThread(pi.hThread); errno= 0; if (__nt_really_exec||__nt_child_nohupped || gui_app){ ExitProcess(0); } else { DWORD exitcode=0; WaitForSingleObject(pi.hProcess,INFINITE); (void)GetExitCodeProcess(pi.hProcess,&exitcode); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); /* * If output was redirected to /dev/clipboard, * we need to close the pipe handles */ if (is_dev_clipboard_active) { CloseHandle((HANDLE)_get_osfhandle(0)); CloseHandle((HANDLE)_get_osfhandle(1)); CloseHandle((HANDLE)_get_osfhandle(2)); CloseHandle(si.hStdInput); CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForSingleObject(ghdevclipthread,60*1000); } ExitProcess(exitcode); } } fail_return: CloseHandle(si.hStdInput); CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); return; }
void nt_execve_wrapped(char *prog, char**args, char**envir ) { STARTUPINFO si; PROCESS_INFORMATION pi; BOOL bRet; DWORD type=0; char *argv0; char **savedargs = args; unsigned int cmdsize,cmdlen; char *cmdstr ,*cmdend; // int rc=0; // unused variable int retries=0; int is_winnt; int hasdot=0; char myself[512]; memset(&si,0,sizeof(si)); /* * This memory is not freed because we are exec()ed and will * not be alive long. */ /* This version avoids realloc in concat_args_and_quote, so it should be a little bit safer */ /* cmdsize = 65500; * cmdstr= heap_alloc(cmdsize); */ cmdsize = MAX_PATH << 2; cmdstr= heap_alloc(MAX_PATH<<2); is_winnt = (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS); /* replace /bin/sh with myself to be executed */ if( strcmp(prog, "/bin/sh") == 0 ) { if (GetModuleFileName(GetModuleHandle(NULL),myself,512) <= 512) { prog = myself; } } cmdlen = copy_quote_and_fix_slashes(prog,cmdstr,&hasdot); cmdend = cmdstr + cmdlen; *cmdend = 0; if (!is_winnt) { argv0 = NULL; goto win95_directly_here; } else { argv0 = heap_alloc(MAX_PATH); wsprintf(argv0,"%s",prog); } retry: bRet=GetBinaryType(argv0,&type); if (is_winnt && !bRet ) { /* Don't append .EXE if it could be a script file */ if (GetLastError() == ERROR_BAD_EXE_FORMAT) { try_shell_ex(args,1); errno = ENOEXEC; return; } else if (retries) { /* If argv[0] got parsed as \\foo (stupid paths with '/' as one * of the components will do it,) and if argv[1] is not the same, * then this is not a real UNC name. * In other cases, argv[0] and argv[1] here must be the same * anyway. -amol 5/1/6/98 */ if ( ( (*prog == '\\') ||(*prog == '/') ) && ( (prog[1] == '\\') ||(prog[1] == '/') ) && ((*args[0] == *prog) && (args[0][1] == prog[1])) && (!args[1]) ) try_shell_ex(args,1); errno = ENOENT; } if (retries > 2) { return; } if (retries == 0) { wsprintf(argv0,"%s.EXE",prog); retries++; } else if (prog[0] == '\\' && retries == 1) { char ptr[80]; if(GetEnvironmentVariable("ZSHROOT",ptr,80)) { wsprintf(argv0,"%s%s",ptr,prog); } retries++; } else if (prog[0] == '\\' && retries == 2) { char ptr[80]; if(GetEnvironmentVariable("ZSHROOT",ptr,80)) { wsprintf(argv0,"%s%s.EXE",ptr,prog); } retries++; } else retries += 2; goto retry; } else if (bRet && retries > 0) { //re-fix argv0 cmdlen = copy_quote_and_fix_slashes(argv0,cmdstr,&hasdot); cmdend = cmdstr + cmdlen; *cmdend = 0; } win95_directly_here: si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = (HANDLE)_get_osfhandle(0); si.hStdOutput = (HANDLE)_get_osfhandle(1); si.hStdError = (HANDLE)_get_osfhandle(2); *args++; // ignore argv[0]; concat_args_and_quote(args,&cmdstr,&cmdlen,&cmdend,&cmdsize); *cmdend = 0; if (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS) { if (!SetConsoleCtrlHandler(NULL,FALSE)) { errno = ENOENT; } } fix_path_for_child(); if (cmdlen < 1000) dprintf("argv0 %s cmdstr %s\n",argv0,cmdstr); if (!CreateProcess(argv0, cmdstr, NULL, NULL, TRUE, // need this for redirecting std handles 0, NULL,//envcrap, NULL, &si, &pi) ) { if (GetLastError() == ERROR_BAD_EXE_FORMAT) { try_shell_ex(savedargs,1); errno = ENOEXEC; } else if (GetLastError() == ERROR_INVALID_PARAMETER) { /* exceeded command line */ errno = ENAMETOOLONG; } else errno = ENOENT; } else { errno= 0; // { DWORD exitcode=0; int gui_app = 0; if (gdwPlatform != VER_PLATFORM_WIN32_WINDOWS) { SetConsoleCtrlHandler(NULL,TRUE); } if (isset(WINNTWAITFORGUIAPPS)) gui_app = 0; else if (is_winnt) gui_app = is_gui(argv0); else gui_app = is_9x_gui(prog); if (!gui_app) { WaitForSingleObject(pi.hProcess,INFINITE); } (void)GetExitCodeProcess(pi.hProcess,&exitcode); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); ExitProcess(exitcode); } } }
int nt_execve(const char *prog, const char *const *args, const char *const *envir) { STARTUPINFO si; PROCESS_INFORMATION pi; enum {none, directex, shellex} execmode; DWORD exitcode; DWORD dwCreationflags; int priority; char *argv0; char *cmdstr, *cmdend; unsigned int cmdsize; size_t prognamelen, cmdlen; int hasext; char extension[_MAX_FNAME]; const char *begin, *end, *extptr; static char exts[MAX_PATH]; UNREFERENCED_PARAMETER(envir); /* get default PATHEXT or use empty exts */ if (!*exts) { DWORD rc; /* not initialized */ rc = GetEnvironmentVariable("PATHEXT", exts, sizeof(exts)); if ((rc == 0) || (rc >= sizeof(exts))) /* if error or PATHEXT too big will retry at the next call */ *exts = 0; } /* if prog has an extension initialize begin end to skip PATHEXT search */ prognamelen = strlen(prog); extptr = prog + prognamelen - 1; hasext = 0; while (extptr > prog && !ISPATHSEP(*extptr)) { if (*extptr == '.' && *(extptr - 1) != ':' && !ISPATHSEP(*(extptr - 1))) { hasext++; break; } extptr--; } if (hasext) { begin = "."; end = ""; strcpy(extension, extptr); } else { begin = exts; end = exts; *extension = '\0'; } argv0 = (char *)heap_alloc(MAX_PATH); /* (prognamelen + 1) does not really matter, argv0 is '\0' filled */ memcpy(argv0, prog, prognamelen + 1); errno = 0; execmode = none; /* NOTE: loops over PATHEXT if no extension found */ while (*begin) { size_t extlen; if (GetBinaryType(argv0, &exitcode)) { /* exists and is executable NOTE: an "xxx.exe" without a correct PE header (i.e. a text file) has type "DOS binary", but execution will generate a WOW error */ execmode = directex; break; } if (GetLastError() == ERROR_BAD_EXE_FORMAT) { /* exists but is not "executable" */ execmode = shellex; break; } if (hasext) break; /* get next PATHEXT extension */ while (*begin && (*begin != '.')) begin++; while (*end && (*end != ';')) end++; if (!*begin) break; extlen = end - begin; if (extlen < sizeof(extension)) { memcpy(extension, begin, extlen); extension[extlen] = '\0'; /* prognamelen ignores the last '\r' if present */ memcpy(argv0, prog, prognamelen); /* update argv0 adding the extension to prog */ memcpy(argv0 + prognamelen, extension, extlen + 1); } begin = end; /* skip sequences of ';' */ while (*end && *end == ';') end++; }; cmdstr = (char *)heap_alloc(MAX_PATH << 2); cmdsize = MAX_PATH << 2; cmdlen = 0; cmdend = cmdstr; dbgprintf(PR_VERBOSE, "%s(): execute [%s] extension=[%s] mode=%d hasext=%d\n", __FUNCTION__, argv0, extension, execmode, hasext); /* skip over program name */ args++; /* the file (after PATHEXT search) exists, but it's not "executable" */ if (execmode == shellex) { /* if prog had no extension or has the extension associated to shell scripts */ if ((hasext == 0 && *extension == '\0') || is_shell_script(extension)) { int res = process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize); if (res < 0) { execmode = none; } else if (res == 0) { char *newargv[2]; cmdlen = copy_quote_and_fix_slashes(gModuleName, cmdstr); cmdend = cmdstr + cmdlen; newargv[0] = path_to_slash(argv0); newargv[1] = NULL; concat_args_and_quote((const char *const *)newargv, &cmdstr, &cmdlen, &cmdend, &cmdsize); *cmdend = 0; argv0 = gModuleName; execmode = directex; } else { cmdend = cmdstr + cmdlen; execmode = directex; } } else { unsigned long shflags = 0L; /* if the file extension is in pathext, use the same console and wait for child. StrStrI() is from shlwapi */ if (StrStrI(exts, extension)) shflags = SEE_MASK_NO_CONSOLE | SEE_MASK_NOCLOSEPROCESS; if (try_shell_ex(argv0, args, shflags, &cmdstr, &cmdsize)) return (0); /* ShellExecute failed, the file has an unknown extension, but it may be a shell script with a shebang */ if (process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize) > 0) { cmdend = cmdstr + cmdlen; execmode = directex; } else { /* the file extension is NOT known and the file has NO shebang: returns EPERM, see NOTES */ errno = EPERM; return (-1); } } } else if (execmode == directex) { cmdlen = copy_quote_and_fix_slashes(prog, cmdstr); cmdend = cmdstr + cmdlen; } if (execmode == none) { /* error: prog not found even after trying PATHEXT extensions */ errno = ENOENT; return (-1); } concat_args_and_quote(args, &cmdstr, &cmdlen, &cmdend, &cmdsize); if (*cmdstr == ' ') { /* if we left a ' ' for the quote and there is no quote */ cmdstr++; cmdlen--; } *cmdend = 0; init_startupinfo(&si); dwCreationflags = GetPriorityClass(GetCurrentProcess()); priority = GetThreadPriority(GetCurrentThread()); #if defined(W32DEBUG) /* DebugView output is very difficult to read with overlong lines */ if (cmdlen < 128) dbgprintf(PR_EXEC, "%s(): CreateProcess(%s, ..) cmdstr=[%s]\n", __FUNCTION__, argv0, cmdstr); else { char shortbuf[128+4]; memcpy(shortbuf, cmdstr, 128); memcpy(shortbuf + 128, "...", 4); dbgprintf(PR_EXEC, "nt_execve(): CreateProcess(%s, ..) cmdstr=[%s]\n", argv0, shortbuf); } #endif if (!CreateProcess(argv0, cmdstr, NULL, NULL, TRUE, // need this for redirecting std handles dwCreationflags | CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { exitcode = GetLastError(); if (exitcode == ERROR_BAD_EXE_FORMAT) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error BAD_EXE_FORMAT in %s\n", argv0, __FUNCTION__); errno = ENOEXEC; } else if (exitcode == ERROR_INVALID_PARAMETER) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error INVALID_PARAMETER in %s, cmdstr len=%u\n", argv0, __FUNCTION__, strlen(cmdstr)); /* exceeded command line */ /* return NOT found, ENAMETOOLONG is correct but not understood by the shell that will retry with another path ... */ errno = ENOENT; } else { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error %ld in %s\n", argv0, exitcode, __FUNCTION__); errno = ENOENT; } goto fail_return; } else { exitcode = 0; if (!SetThreadPriority(pi.hThread, priority)) dbgprintf(PR_ERROR, "!!! SetThreadPriority(0x%p) failed, error %ld\n", pi.hThread, GetLastError()); ResumeThread(pi.hThread); if (!is_gui(argv0)) { if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) dbgprintf(PR_ERROR, "!!! error %ld waiting for process %ld\n", GetLastError(), pi.dwProcessId); if (!GetExitCodeProcess(pi.hProcess, &exitcode)) dbgprintf(PR_ERROR, "!!! GetExitCodeProcess(0x%p, ..) error %ld in %s\n", pi.hProcess, GetLastError(), __FUNCTION__); } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); close_si_handles(); /* @@@@ should wait for the clipboard ? if (is_dev_clipboard_active) { CloseHandle((HANDLE)_get_osfhandle(0)); CloseHandle((HANDLE)_get_osfhandle(1)); CloseHandle((HANDLE)_get_osfhandle(2)); ... WaitForSingleObject(ghdevclipthread,60*1000); } */ dbgprintf(PR_ALL, "--- %s(): Exec'd process %ld terminated with exitcode %ld\n", __FUNCTION__, pi.dwProcessId, exitcode); exec_exit((int)exitcode); } fail_return: heap_free(cmdstr); close_si_handles(); exec_exit(-1); return (-1); }