Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / prex-0.9.0 / usr / lib / libc / gen / execvp.c @ 03e9c04a

History | View | Annotate | Download (3.65 KB)

1 03e9c04a Brad Neuman
/*-
2
 * Copyright (c) 1991, 1993
3
 *        The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the University nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include <sys/cdefs.h>
31
#include <assert.h>
32
#include <errno.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <limits.h>
37
#include <paths.h>
38
#include <unistd.h>
39
40
extern char **environ;
41
42
int
43
execvp(const char *name, char * const *argv)
44
{
45
        const char **memp;
46
        int cnt;
47
        size_t lp, ln = 0;
48
        int eacces = 0;
49
        unsigned int etxtbsy = 0;
50
        char buf[PATH_MAX];
51
        const char *bp, *path, *p;
52
53
        /* "" is not a valid filename; check this before traversing PATH. */
54
        if (name[0] == '\0') {
55
                errno = ENOENT;
56
                goto done;
57
        }
58
        /* If it's an absolute or relative path name, it's easy. */
59
        if (strchr(name, '/')) {
60
                bp = name;
61
                path = "";
62
                goto retry;
63
        }
64
        bp = buf;
65
66
        /* Get the path we're searching. */
67
        if (!(path = getenv("PATH")))
68
                path = _PATH_DEFPATH;
69
70
        ln = strlen(name);
71
        do {
72
                /* Find the end of this path element. */
73
                for (p = path; *path != 0 && *path != ':'; path++)
74
                        continue;
75
                /*
76
                 * It's a SHELL path -- double, leading and trailing colons
77
                 * mean the current directory.
78
                 */
79
                if (p == path) {
80
                        p = ".";
81
                        lp = 1;
82
                } else
83
                        lp = path - p;
84
85
                /*
86
                 * If the path is too long complain.  This is a possible
87
                 * security issue; given a way to make the path too long
88
                 * the user may execute the wrong program.
89
                 */
90
                if (lp + ln + 2 > sizeof(buf))
91
                        continue;
92
                memcpy(buf, p, lp);
93
                buf[lp] = '/';
94
                memcpy(buf + lp + 1, name, ln);
95
                buf[lp + ln + 1] = '\0';
96
97
retry:                (void)execve(bp, argv, environ);
98
                switch (errno) {
99
                case EACCES:
100
                        eacces = 1;
101
                        break;
102
                case ENOTDIR:
103
                case ENOENT:
104
                        break;
105
                case ENOEXEC:
106
                        for (cnt = 0; argv[cnt] != NULL; ++cnt)
107
                                continue;
108
                        if ((memp = (const char **)(alloca((cnt + 2) * sizeof(*memp)))) == NULL)
109
                                goto done;
110
                        memp[0] = _PATH_BSHELL;
111
                        memp[1] = bp;
112
                        (void)memcpy(&memp[2], &argv[1], cnt * sizeof(*memp));
113
                        (void)execve(_PATH_BSHELL, (char * const *)memp,
114
                            environ);
115
                        goto done;
116
                case ETXTBSY:
117
                        if (etxtbsy < 3)
118
                                (void)sleep(++etxtbsy);
119
                        goto retry;
120
                default:
121
                        goto done;
122
                }
123
        } while (*path++ == ':');        /* Otherwise, *path was NUL */
124
        if (eacces)
125
                errno = EACCES;
126
        else if (!errno)
127
                errno = ENOENT;
128
done:
129
        return (-1);
130
}