Beispiel #1
0
void try_shell_ex(char **argv,int exitsuccess, BOOL throw_ok) {/*FIXRESET*/

	char *prog;
	char *cmdstr, *p2, *cmdend;
	char *originalPtr = NULL;
	unsigned int cmdsize,cmdlen;
	char err2[256];
	char *ptr;
	SHELLEXECUTEINFO shinfo;
	unsigned long  mask = SEE_MASK_FLAG_NO_UI;
	BOOL rc;
	char *extension;

	prog=*argv;

	dprintf("trying shellex for prog %s\n",prog);
	ptr = prog;
	if (!is_url(prog)) {

		while(*ptr) {
			if (*ptr == '/')
				*ptr = '\\';
			ptr++;
		}

		extension = ptr;

		// search back for "."
		while(extension != prog) {
			if (*extension == '.') {
				extension++;
				break;
			}
			else
				extension--;
		}
		/* check if this matches a member in the no_assoc array.
		 */
		if (extension != prog)  {
			if (find_no_assoc(extension))
				return;
		}

	}
	originalPtr = cmdstr= heap_alloc(MAX_PATH<<2);

	cmdsize = MAX_PATH<<2;

	p2 = cmdstr;

	cmdlen = 0;
	cmdend = p2;

	argv++; // the first arg is the command


	dprintf("try_shell_ex calling c_a_a_q");
	if(!concat_args_and_quote(argv,&originalPtr,&cmdstr,&cmdlen,&cmdend,&cmdsize))
	{
		errno = ENOMEM;
		heap_free(originalPtr);
		return;
	}

	*cmdend = 0;


	memset(&shinfo,0,sizeof(shinfo));
	shinfo.cbSize = sizeof(shinfo);
	shinfo.fMask = SEE_MASK_FLAG_DDEWAIT | mask;
	shinfo.hwnd = NULL;
	shinfo.lpVerb = NULL;
	shinfo.lpFile = prog;
	shinfo.lpParameters = &cmdstr[0];
	shinfo.lpDirectory = 0;
	shinfo.nShow = SW_SHOWDEFAULT;


	ptr = fix_path_for_child();

	rc = pShellExecuteEx(&shinfo);
	if (rc ) {
		if (exitsuccess) 
			ExitProcess(0);
		errno = 0;

		heap_free(originalPtr);
		return;
	}
	if (throw_ok) { 
		// if we got here, ShellExecuteEx failed, so reset() via stderror()
		// this may cause the caller to leak, but the assumption is that
		// only a child process sets exitsuccess, so it will be dead soon
		// anyway

		restore_path(ptr);

		make_err_str(GetLastError(),cmdstr,512);//don't need the full size
		(void)StringCbPrintf(err2,sizeof(err2),"%s",prog);
		stderror(ERR_SYSTEM,err2,cmdstr);/*FIXRESET*/
	}

	heap_free(originalPtr);
	restore_path(ptr);

	errno = ENOEXEC;

}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
        }
    }
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
static int process_shebang(char *argv0, const char *const *cmdstr, size_t *cmdlen, char **cmdend, unsigned int *cmdsize)
{
	HANDLE hfile;
	char buf[512];
	unsigned int nn, t0;
	char *ptr, *ptr2;
	char *newargv[4];
	char pbuffer[MAX_PATH];
	char *filepart;
	static const char *shellnames[] = {"/bin/sh", "/bin/zsh", "/bin/ksh"};
	static const char usrbinenv[] = "/usr/bin/env";
	static const char usrbinpython[] = "/usr/bin/python";
	static const char usrbinperl[] = "/usr/bin/perl";
	static const char usrbintcl[] = "/usr/bin/tcl";

	hfile = CreateFile(argv0, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
			   NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hfile == INVALID_HANDLE_VALUE)
		return (-1);
	if (!ReadFile(hfile, buf, (DWORD)sizeof(buf), (DWORD *)&nn, NULL)) {
		CloseHandle(hfile);
		return (-1);
	}
	CloseHandle(hfile);
	if (!((nn >= 3) && (buf[0] == '#') && (buf[1] == '!')))
		return (0);

	/* this code is more or less what zexecve() does */
	for (t0 = 0; t0 != nn; t0++)
		if ((buf[t0] == '\n') || (buf[t0] == '\r'))
			break;
	while (isspace(buf[t0]))
		buf[t0--] = '\0';
	buf[sizeof(buf)-1] = '\0';
	/* @@@@ fails for "/b/s p/pgm" !!! */
	for (ptr = buf + 2; *ptr && *ptr == ' '; ptr++)
		;
	for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++)
		;
	/* ptr2 is the program name, ptr points to the args */
	dbgprintf(PR_VERBOSE, "%s(): found \"!#\" program=[%s] arg ptr=[%s]\n", __FUNCTION__, ptr2, *ptr ? ptr + 1 : "NULL");
	/* append to the cmdstr
	   should have argv0 ('/' or '\' format ?) */
	if (*ptr) {
		*ptr = '\0';
		newargv[0] = ptr2;
		newargv[1] = ptr + 1;
		newargv[2] = argv0;
	} else {
		newargv[0] = ptr2;
		newargv[1] = argv0;
		newargv[2] = NULL;
	}
	newargv[3] = NULL;
	concat_args_and_quote((const char *const *)newargv, (char **)cmdstr, cmdlen, cmdend, cmdsize);
	*cmdend = '\0';
	/* if ptr2 is a "well known" shell name set argv0 to our module name */
	for (nn = 0; nn < LENGTH_OF(shellnames); nn++) {
		if (strcmp(ptr2, shellnames[nn]) == 0) {
			strcpy(argv0, gModuleName);
			return (1);
		}
	}
	if (strcmp(ptr2, usrbinenv) == 0) {
		SearchPath(NULL, "env.exe", NULL, sizeof(pbuffer), pbuffer, &filepart);
		strcpy(argv0, pbuffer);
	} else if (strcmp(ptr2, usrbinpython) == 0) {
		SearchPath(NULL, "python.exe", NULL, sizeof(pbuffer), pbuffer, &filepart);
		strcpy(argv0, pbuffer);
	} else if (strcmp(ptr2, usrbinperl) == 0) {
		SearchPath(NULL, "perl.exe", NULL, sizeof(pbuffer), pbuffer, &filepart);
		strcpy(argv0, pbuffer);
	} else if (strcmp(ptr2, usrbintcl) == 0) {
		SearchPath(NULL, "tcl.exe", NULL, sizeof(pbuffer), pbuffer, &filepart);
		strcpy(argv0, pbuffer);
	} else {
		char *exeptr;
		path_to_backslash(ptr2);
		strcpy(argv0, ptr2);
		/* if argv0 does not end with ".exe" add ".exe" */
		exeptr = StrStrI(argv0, ".exe");
		if ((exeptr == NULL) || (exeptr != strrchr(argv0, '.'))) {
			strcat(argv0, ".exe");
			dbgprintf(PR_VERBOSE, "%s(): argv0 modified to [%s]\n", __FUNCTION__, argv0);
		}
	}
	return (1);
}
Beispiel #7
0
static int try_shell_ex(char *argv0, const char *const *argv, unsigned long shellexflags, char **cmdstr, unsigned int *cmdsize)
{
	char *cmdend;
	size_t cmdlen;
	SHELLEXECUTEINFO shinfo;
	BOOL nocmd = 0;

	path_to_backslash(argv0);

	/* @@@@ is this code really needed ? when ? */
	if ((!*argv) && (argv0[0] == '\\') && (argv0[1] == '\\')) {
		shellexflags |= SEE_MASK_CONNECTNETDRV;
		nocmd = 1;
		goto noargs;
	}

	cmdend = *cmdstr;
	cmdlen = 0;
	concat_args_and_quote(argv, cmdstr, &cmdlen, &cmdend, cmdsize);
	*cmdend = '\0';

noargs:
	dbgprintf(PR_EXEC, "ShellExecute(%s, ..) with cmdstr [%s]\n", argv0, *cmdstr);
	memset(&shinfo, 0, sizeof(shinfo));
	shinfo.cbSize = sizeof(shinfo);
	shinfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_FLAG_DDEWAIT | shellexflags;
	shinfo.hwnd = NULL;
	shinfo.lpVerb = NULL;
	shinfo.lpFile = argv0;
	shinfo.lpParameters = nocmd ? NULL : *cmdstr;
	shinfo.lpDirectory = 0;
	shinfo.nShow = SW_SHOWDEFAULT;

	if (ShellExecuteEx(&shinfo)) {
		DWORD retval = 255;
		dbgprintf(PR_EXEC, "ShellExecute() created process handle 0x%p\n", shinfo.hProcess);
		/* may happen if "executing" a file associated to a running program, i.e.
		   "execute" a .html file with an already opened browser window */
		if (shinfo.hProcess != (HANDLE)0) {
			if (shellexflags & SEE_MASK_NOCLOSEPROCESS) {
				if ((intptr_t)(shinfo.hInstApp) > 32) {
					if (WaitForSingleObject(shinfo.hProcess, INFINITE) == WAIT_OBJECT_0) {
						/* try to get the return value */
						GetExitCodeProcess(shinfo.hProcess, &retval);
					} else {
						dbgprintf(PR_ERROR, "!!! ShellExecute() [%s] WaitForSingleObject() error %ld\n", argv0, GetLastError());
					}
				} else {
					dbgprintf(PR_ERROR, "!!! ShellExecute() [%s] error %p\n", argv0, shinfo.hInstApp);
				}
			}
			/* try to close, it may fail but .. what else could we do */
			CloseHandle(shinfo.hProcess);
		}
		dbgprintf(PR_ALL, "--- %s(): ShellExecute() OK, exiting with code %ld\n", __FUNCTION__, retval);
		exec_exit((int)retval);
	} else {
		dbgprintf(PR_EXEC, "ShellExecute() failed\n");
	}
       	return (0);
}