1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <alloca.h>
21: #include <unistd.h>
22: #include <stdarg.h>
23: #include <stdbool.h>
24: #include <stdlib.h>
25: #include <string.h>
26: #include <errno.h>
27: #include <paths.h>
28:
29:
30:
31:
32: static void
33: internal_function
34: scripts_argv (const char *file, char *const argv[], int argc, char **new_argv)
35: {
36:
37: new_argv[0] = (char *) _PATH_BSHELL;
38: new_argv[1] = (char *) file;
39: while (argc > 1)
40: {
41: new_argv[argc] = argv[argc - 1];
42: --argc;
43: }
44: }
45:
46:
47:
48:
49: int
50: execvp (file, argv)
51: const char *file;
52: char *const argv[];
53: {
54: if (*file == '\0')
55: {
56:
57: __set_errno (ENOENT);
58: return -1;
59: }
60:
61: if (strchr (file, '/') != NULL)
62: {
63:
64: __execve (file, argv, __environ);
65:
66: if (errno == ENOEXEC)
67: {
68:
69: int argc = 0;
70: while (argv[argc++])
71: ;
72: size_t len = (argc + 1) * sizeof (char *);
73: char **script_argv;
74: void *ptr = NULL;
75: if (__libc_use_alloca (len))
76: script_argv = alloca (len);
77: else
78: script_argv = ptr = malloc (len);
79:
80: if (script_argv != NULL)
81: {
82: scripts_argv (file, argv, argc, script_argv);
83: __execve (script_argv[0], script_argv, __environ);
84:
85: free (ptr);
86: }
87: }
88: }
89: else
90: {
91: size_t pathlen;
92: size_t alloclen = 0;
93: char *path = getenv ("PATH");
94: if (path == NULL)
95: {
96: pathlen = confstr (_CS_PATH, (char *) NULL, 0);
97: alloclen = pathlen + 1;
98: }
99: else
100: pathlen = strlen (path);
101:
102: size_t len = strlen (file) + 1;
103: alloclen += pathlen + len + 1;
104:
105: char *name;
106: char *path_malloc = NULL;
107: if (__libc_use_alloca (alloclen))
108: name = alloca (alloclen);
109: else
110: {
111: path_malloc = name = malloc (alloclen);
112: if (name == NULL)
113: return -1;
114: }
115:
116: if (path == NULL)
117: {
118:
119:
120:
121: path = name + pathlen + len + 1;
122: path[0] = ':';
123: (void) confstr (_CS_PATH, path + 1, pathlen);
124: }
125:
126:
127: name = (char *) memcpy (name + pathlen + 1, file, len);
128:
129: *--name = '/';
130:
131: char **script_argv = NULL;
132: void *script_argv_malloc = NULL;
133: bool got_eacces = false;
134: char *p = path;
135: do
136: {
137: char *startp;
138:
139: path = p;
140: p = __strchrnul (path, ':');
141:
142: if (p == path)
143:
144:
145: startp = name + 1;
146: else
147: startp = (char *) memcpy (name - (p - path), path, p - path);
148:
149:
150: __execve (startp, argv, __environ);
151:
152: if (errno == ENOEXEC)
153: {
154: if (script_argv == NULL)
155: {
156:
157: int argc = 0;
158: while (argv[argc++])
159: ;
160: size_t arglen = (argc + 1) * sizeof (char *);
161: if (__libc_use_alloca (alloclen + arglen))
162: script_argv = alloca (arglen);
163: else
164: script_argv = script_argv_malloc = malloc (arglen);
165: if (script_argv == NULL)
166: {
167:
168:
169: got_eacces = false;
170: break;
171: }
172: scripts_argv (startp, argv, argc, script_argv);
173: }
174:
175: __execve (script_argv[0], script_argv, __environ);
176: }
177:
178: switch (errno)
179: {
180: case EACCES:
181:
182:
183:
184: got_eacces = true;
185: case ENOENT:
186: case ESTALE:
187: case ENOTDIR:
188:
189:
190:
191: case ENODEV:
192: case ETIMEDOUT:
193:
194:
195:
196: break;
197:
198: default:
199:
200:
201:
202: return -1;
203: }
204: }
205: while (*p++ != '\0');
206:
207:
208: if (got_eacces)
209:
210:
211: __set_errno (EACCES);
212:
213: free (script_argv_malloc);
214: free (path_malloc);
215: }
216:
217:
218: return -1;
219: }
220: libc_hidden_def (execvp)