示例#1
0
文件: execvp.c 项目: htchiang/zeke
int execvp(const char * name, char * const argv[])
{
    char * pathstr;
    char * cp;
    char fname[NAME_MAX];
    unsigned etxtbsy = 1;
    int eacces = 0;

    pathstr = getenv("PATH");
    if (!pathstr)
        pathstr = _PATH_STDPATH;
    cp = strchr(name, '/') ? "" : pathstr;

    do {
        cp = execat(cp, name, fname);
    retry:
        execve(fname, argv, environ);
        switch (errno) {
        case ENOEXEC:
            return exec_script(argv, fname);
        case ETXTBSY:
            if (++etxtbsy > 5)
                return -1;
            sleep(etxtbsy);
            goto retry;
        case EACCES:
            eacces = 1;
            break;
        case E2BIG:
        case EFAULT:
        case ENOMEM:
            return -1;
        }
    } while (cp);

    if (eacces)
        errno = EACCES;
    return -1;
}
示例#2
0
/* ARGSUSED */
int
posix_spawnp(
	pid_t *pidp,
	const char *file,
	const posix_spawn_file_actions_t *file_actions,
	const posix_spawnattr_t *attrp,
	char *const argv[],
	char *const envp[])
{
	spawn_attr_t *sap = attrp? attrp->__spawn_attrp : NULL;
	file_attr_t *fap = file_actions? file_actions->__file_attrp : NULL;
	void *dirbuf = NULL;
	const char *pathstr = (strchr(file, '/') == NULL)? getenv("PATH") : "";
	int xpg4 = libc__xpg4;
	int error = 0;		/* this will be set by the child */
	char path[PATH_MAX+4];
	const char *cp;
	pid_t pid;
	char **newargs;
	int argc;
	int i;

	if (attrp != NULL && sap == NULL)
		return (EINVAL);

	if (*file == '\0')
		return (EACCES);

	if (fap != NULL && fap->fa_need_dirbuf) {
		/*
		 * Preallocate the buffer for the call to getdents64() in
		 * spawn_closefrom() since we can't do it in the vfork() child.
		 */
		if ((dirbuf = lmalloc(DIRBUF)) == NULL)
			return (ENOMEM);
	}

	/*
	 * We may need to invoke the shell with a slightly modified
	 * argv[] array.  To do this we need to preallocate the array.
	 * We must call alloca() before calling vfork() because doing
	 * it after vfork() (in the child) would corrupt the parent.
	 */
	for (argc = 0; argv[argc] != NULL; argc++)
		continue;
	newargs = alloca((argc + 2) * sizeof (char *));

	switch (pid = vforkx(forkflags(sap))) {
	case 0:			/* child */
		break;
	case -1:		/* parent, failure */
		if (dirbuf)
			lfree(dirbuf, DIRBUF);
		return (errno);
	default:		/* parent, success */
		/*
		 * We don't get here until the child exec()s or exit()s
		 */
		if (pidp != NULL && get_error(&error) == 0)
			*pidp = pid;
		if (dirbuf)
			lfree(dirbuf, DIRBUF);
		return (get_error(&error));
	}

	if (sap != NULL)
		if (set_error(&error, perform_flag_actions(sap)) != 0)
			_exit(_EVAPORATE);

	if (fap != NULL)
		if (set_error(&error, perform_file_actions(fap, dirbuf)) != 0)
			_exit(_EVAPORATE);

	if (pathstr == NULL) {
		/*
		 * XPG4:  pathstr is equivalent to _CS_PATH, except that
		 * :/usr/sbin is appended when root, and pathstr must end
		 * with a colon when not root.  Keep these paths in sync
		 * with _CS_PATH in confstr.c.  Note that pathstr must end
		 * with a colon when not root so that when file doesn't
		 * contain '/', the last call to execat() will result in an
		 * attempt to execv file from the current directory.
		 */
		if (geteuid() == 0 || getuid() == 0) {
			if (!xpg4)
				pathstr = "/usr/sbin:/usr/ccs/bin:/usr/bin";
			else
				pathstr = "/usr/xpg4/bin:/usr/ccs/bin:"
				    "/usr/bin:/opt/SUNWspro/bin:/usr/sbin";
		} else {
			if (!xpg4)
				pathstr = "/usr/ccs/bin:/usr/bin:";
			else
				pathstr = "/usr/xpg4/bin:/usr/ccs/bin:"
				    "/usr/bin:/opt/SUNWspro/bin:";
		}
	}

	cp = pathstr;
	do {
		cp = execat(cp, file, path);
		/*
		 * 4025035 and 4038378
		 * if a filename begins with a "-" prepend "./" so that
		 * the shell can't interpret it as an option
		 */
		if (*path == '-') {
			char *s;

			for (s = path; *s != '\0'; s++)
				continue;
			for (; s >= path; s--)
				*(s + 2) = *s;
			path[0] = '.';
			path[1] = '/';
		}
		(void) set_error(&error, 0);
		(void) execve(path, argv, envp);
		if (set_error(&error, errno) == ENOEXEC) {
			newargs[0] = "sh";
			newargs[1] = path;
			for (i = 1; i <= argc; i++)
				newargs[i + 1] = argv[i];
			(void) set_error(&error, 0);
			(void) execve(_PATH_BSHELL, newargs, envp);
			if (sap != NULL &&
			    (sap->sa_psflags & POSIX_SPAWN_NOEXECERR_NP))
				_exit(127);
			(void) set_error(&error, errno);
			_exit(_EVAPORATE);
		}
	} while (cp);

	if (sap != NULL &&
	    (sap->sa_psflags & POSIX_SPAWN_NOEXECERR_NP)) {
		(void) set_error(&error, 0);
		_exit(127);
	}
	_exit(_EVAPORATE);
	return (0);	/* not reached */
}
示例#3
0
文件: exec.c 项目: alhazred/onarm
/*
 * Similiar to execvp(), execpt you can supply an environment and we always
 * use /bin/sh for shell scripts.  The PATH searched is the PATH in the
 * current environment, not the environment in the argument list.
 * This was pretty much stolen from libc/gen/port/execvp.c
 */
static int
execvpe(char *name, char *const argv[], char *const envp[])
{
	char *path;
	char fname[PATH_MAX+2];
	char *newargs[256];
	int i;
	const char *cp;
	unsigned etxtbsy = 1;
        int eacces = 0;

	if (*name == '\0') {
		errno = ENOENT;
		return (-1);
	}

	if ((path = getenv("PATH")) == NULL)
		path = "/usr/bin:/bin";

        cp = strchr(name, '/')? (const char *)"": path;

        do {
                cp = execat(cp, name, fname);
        retry:
                /*
                 * 4025035 and 4038378
                 * if a filename begins with a "-" prepend "./" so that
                 * the shell can't interpret it as an option
                 */
                if (*fname == '-') {
                        size_t size = strlen(fname) + 1;
                        if ((size + 2) > sizeof (fname)) {
                                errno = E2BIG;
                                return (-1);
                        }
                        (void) memmove(fname + 2, fname, size);
                        fname[0] = '.';
                        fname[1] = '/';
                }
                (void) execve(fname, argv, envp);
                switch (errno) {
                case ENOEXEC:
                        newargs[0] = "sh";
                        newargs[1] = fname;
                        for (i = 1; (newargs[i + 1] = argv[i]) != NULL; ++i) {
                                if (i >= 254) {
                                        errno = E2BIG;
                                        return (-1);
                                }
                        }
                        (void) execve("/bin/sh", newargs, envp);
                        return (-1);
                case ETXTBSY:
                        if (++etxtbsy > 5)
                                return (-1);
                        (void) sleep(etxtbsy);
                        goto retry;
                case EACCES:
                        ++eacces;
                        break;
                case ENOMEM:
                case E2BIG:
                case EFAULT:
                        return (-1);
                }
        } while (cp);
        if (eacces)
                errno = EACCES;
        return (-1);
}