OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [unistd/] [exec.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*  Copyright (C) 2004     Manuel Novoa III
2
 *
3
 *  This library is free software; you can redistribute it and/or
4
 *  modify it under the terms of the GNU Library General Public
5
 *  License as published by the Free Software Foundation; either
6
 *  version 2 of the License, or (at your option) any later version.
7
 *
8
 *  This library is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 *  Library General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU Library General Public
14
 *  License along with this library; if not, write to the Free
15
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
17
 
18
/* Jan 1, 2004
19
 *   Initial version of a SUSv3 compliant exec*() functions.
20
 */
21
 
22
/* NOTE: Strictly speaking, there could be problems from accessing
23
 * __environ in multithreaded programs.  The only way around this
24
 * that I see is to essentially lock __environ access (modifying
25
 * the setenv code), make a copy of the environment table (just the
26
 * pointers since the strings themselves are never freed), and then
27
 * unlock prior to the execve call.  If that fails, then we'd need
28
 * to free the storage allocated for the copy.  Better ideas anyone?
29
 */
30
 
31
#define _GNU_SOURCE
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <errno.h>
36
#include <stdarg.h>
37
#include <limits.h>
38
#include <unistd.h>
39
#include <sys/mman.h>
40
 
41
extern char *__strchrnul(const char *s, int c);
42
 
43
/**********************************************************************/
44
#ifdef __UCLIBC_HAS_MMU__
45
 
46
/* We have an MMU, so use alloca() to grab space for buffers and
47
 * arg lists. */
48
 
49
# define EXEC_ALLOC_SIZE(VAR)   /* nothing to do */
50
# define EXEC_ALLOC(SIZE,VAR)   alloca((SIZE))
51
# define EXEC_FREE(PTR,VAR)             ((void)0)
52
 
53
#else
54
 
55
/* We do not have an MMU, so using alloca() is not an option.
56
 * Less obviously, using malloc() is not an option either since
57
 * malloc()ed memory can leak in a vfork() and exec*() situation.
58
 * Therefore, we must use mmap() and unmap() directly.
59
 */
60
 
61
# define EXEC_ALLOC_SIZE(VAR)   size_t VAR;     /* Semicolon included! */
62
# define EXEC_ALLOC(SIZE,VAR)   __exec_alloc((VAR = (SIZE)))
63
# define EXEC_FREE(PTR,VAR)             __exec_free((PTR),(VAR))
64
 
65
extern void *__exec_alloc(size_t size);
66
extern void __exec_free(void *ptr, size_t size);
67
 
68
#endif
69
/**********************************************************************/
70
#ifdef L___exec_alloc
71
 
72
#ifndef __UCLIBC_HAS_MMU__
73
 
74
void *__exec_alloc(size_t size)
75
{
76
        void *p;
77
 
78
        p = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
79
 
80
        return (p != MAP_FAILED) ? p : NULL;
81
}
82
 
83
void __exec_free(void *ptr, size_t size)
84
{
85
        if (ptr) {
86
                munmap(ptr, size);
87
        }
88
}
89
 
90
#endif
91
 
92
#endif
93
/**********************************************************************/
94
#ifdef L_execl
95
 
96
int execl(const char *path, const char *arg, ...)
97
{
98
        EXEC_ALLOC_SIZE(size)           /* Do NOT add a semicolon! */
99
        int n;
100
        char **argv;
101
        char **p;
102
        va_list args;
103
 
104
        n = 0;
105
        va_start(args, arg);
106
        do {
107
                ++n;
108
        } while (va_arg(args, char *));
109
        va_end(args);
110
 
111
        p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size);
112
 
113
        p[0] = (char *)arg;
114
 
115
        va_start(args, arg);
116
        do {
117
                *++p = va_arg(args, char *);
118
        } while (--n);
119
        va_end(args);
120
 
121
        n = execve(path, (char *const *) argv, __environ);
122
 
123
        EXEC_FREE(argv, size);
124
 
125
        return n;
126
}
127
 
128
#endif
129
/**********************************************************************/
130
#ifdef L_execv
131
 
132
int execv(__const char *path, char *__const argv[])
133
{
134
        return execve(path, argv, __environ);
135
}
136
 
137
#endif
138
/**********************************************************************/
139
#ifdef L_execle
140
 
141
int execle(const char *path, const char *arg, ...)
142
{
143
        EXEC_ALLOC_SIZE(size)           /* Do NOT add a semicolon! */
144
        int n;
145
        char **argv;
146
        char **p;
147
        char *const *envp;
148
        va_list args;
149
 
150
        n = 0;
151
        va_start(args, arg);
152
        do {
153
                ++n;
154
        } while (va_arg(args, char *));
155
        envp = va_arg(args, char *const *);     /* Varies from execl and execlp. */
156
        va_end(args);
157
 
158
        p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size);
159
 
160
        p[0] = (char *)arg;
161
 
162
        va_start(args, arg);
163
        do {
164
                *++p = va_arg(args, char *);
165
        } while (--n);
166
        va_end(args);
167
 
168
        n = execve(path, (char *const *) argv, envp);
169
 
170
        EXEC_FREE(argv, size);
171
 
172
        return n;
173
}
174
 
175
#endif
176
/**********************************************************************/
177
#ifdef L_execlp
178
 
179
int execlp(const char *file, const char *arg, ...)
180
{
181
        EXEC_ALLOC_SIZE(size)           /* Do NOT add a semicolon! */
182
        int n;
183
        char **argv;
184
        char **p;
185
        va_list args;
186
 
187
        n = 0;
188
        va_start(args, arg);
189
        do {
190
                ++n;
191
        } while (va_arg(args, char *));
192
        va_end(args);
193
 
194
        p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size);
195
 
196
        p[0] = (char *)arg;
197
 
198
        va_start(args, arg);
199
        do {
200
                *++p = va_arg(args, char *);
201
        } while (--n);
202
        va_end(args);
203
 
204
        n = execvp(file, (char *const *) argv);
205
 
206
        EXEC_FREE(argv, size);
207
 
208
        return n;
209
}
210
 
211
#endif
212
/**********************************************************************/
213
#ifdef L_execvp
214
 
215
/* Use a default path that matches glibc behavior, since SUSv3 says
216
 * this is implementation-defined.  The default is current working dir,
217
 * /bin, and then /usr/bin. */
218
static const char default_path[] = ":/bin:/usr/bin";
219
 
220
int execvp(const char *path, char *const argv[])
221
{
222
        char *buf = NULL;
223
        char *p;
224
        char *e;
225
        char *s0;
226
        char *s;
227
        EXEC_ALLOC_SIZE(size = 0)        /* Do NOT add a semicolon! */
228
        size_t len;
229
        size_t plen;
230
 
231
        if (!path || !*path) {          /* Comply with SUSv3. */
232
        BAD:
233
                __set_errno(ENOENT);
234
                return -1;
235
        }
236
 
237
        if (strchr(path, '/')) {
238
                execve(path, argv, __environ);
239
        CHECK_ENOEXEC:
240
                if (errno == ENOEXEC) {
241
                        char **nargv;
242
                        EXEC_ALLOC_SIZE(size2) /* Do NOT add a semicolon! */
243
                        size_t n;
244
                        /* Need the dimension - 1.  We omit counting the trailing
245
                         * NULL but we actually omit the first entry. */
246
                        for (n=0 ; argv[n] ; n++) {}
247
                        nargv = (char **) EXEC_ALLOC((n+2) * sizeof(char *), size2);
248
                        nargv[0] = argv[0];
249
                        nargv[1] = (char *)path;
250
                        memcpy(nargv+2, argv+1, n*sizeof(char *));
251
                        execve("/bin/sh", nargv, __environ);
252
                        EXEC_FREE(nargv, size2);
253
                }
254
        } else {
255
                if ((p = getenv("PATH")) != NULL) {
256
                        if (!*p) {
257
                                goto BAD;
258
                        }
259
                } else {
260
                        p = (char *) default_path;
261
                }
262
 
263
                plen = strlen(path);
264
                if (plen > (FILENAME_MAX - 1)) {
265
                ALL_TOO_LONG:
266
                        __set_errno(ENAMETOOLONG);
267
                        return -1;
268
                }
269
                len = (FILENAME_MAX - 1) - plen;
270
 
271
                if ((buf = EXEC_ALLOC(FILENAME_MAX, size)) != NULL) {
272
                        int seen_small = 0;
273
                        s0 = buf + len;
274
                        memcpy(s0, path, plen+1);
275
 
276
                        do {
277
                                s = s0;
278
                                e = __strchrnul(p, ':');
279
                                if (e > p) {
280
                                        plen = e - p;
281
                                        if (e[-1] != '/') {
282
                                                ++plen;
283
                                        }
284
                                        if (plen > len) {
285
                                                goto NEXT;
286
                                        }
287
                                        s -= plen;
288
                                        memcpy(s, p, plen);
289
                                        s[plen-1] = '/';
290
                                }
291
 
292
                                execve(s, argv, __environ);
293
 
294
                                seen_small = 1;
295
 
296
                                if (errno != ENOENT) {
297
                                        path = s;
298
                                        goto CHECK_ENOEXEC;
299
                                }
300
 
301
                        NEXT:
302
                                if (!*e) {
303
                                        if (!seen_small) {
304
                                                goto ALL_TOO_LONG;
305
                                        }
306
                                        break;
307
                                }
308
                                p = e + 1;
309
                        } while (1);
310
                }
311
        }
312
 
313
        EXEC_FREE(buf, size);
314
 
315
        return -1;
316
}
317
 
318
#endif
319
/**********************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.