GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/gen/exec.c Lines: 0 98 0.0 %
Date: 2017-11-13 Branches: 0 62 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: exec.c,v 1.23 2016/03/13 18:34:20 guenther Exp $ */
2
/*-
3
 * Copyright (c) 1991, 1993
4
 *	The Regents of the University of California.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
#include <sys/types.h>
32
#include <sys/uio.h>
33
34
#include <errno.h>
35
#include <limits.h>
36
#include <paths.h>
37
#include <stdarg.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
43
int
44
execl(const char *name, const char *arg, ...)
45
{
46
	va_list ap;
47
	char **argv;
48
	int n;
49
50
	va_start(ap, arg);
51
	n = 1;
52
	while (va_arg(ap, char *) != NULL)
53
		n++;
54
	va_end(ap);
55
	argv = alloca((n + 1) * sizeof(*argv));
56
	if (argv == NULL) {
57
		errno = ENOMEM;
58
		return (-1);
59
	}
60
	va_start(ap, arg);
61
	n = 1;
62
	argv[0] = (char *)arg;
63
	while ((argv[n] = va_arg(ap, char *)) != NULL)
64
		n++;
65
	va_end(ap);
66
	return (execve(name, argv, environ));
67
}
68
DEF_WEAK(execl);
69
70
int
71
execle(const char *name, const char *arg, ...)
72
{
73
	va_list ap;
74
	char **argv, **envp;
75
	int n;
76
77
	va_start(ap, arg);
78
	n = 1;
79
	while (va_arg(ap, char *) != NULL)
80
		n++;
81
	va_end(ap);
82
	argv = alloca((n + 1) * sizeof(*argv));
83
	if (argv == NULL) {
84
		errno = ENOMEM;
85
		return (-1);
86
	}
87
	va_start(ap, arg);
88
	n = 1;
89
	argv[0] = (char *)arg;
90
	while ((argv[n] = va_arg(ap, char *)) != NULL)
91
		n++;
92
	envp = va_arg(ap, char **);
93
	va_end(ap);
94
	return (execve(name, argv, envp));
95
}
96
97
int
98
execlp(const char *name, const char *arg, ...)
99
{
100
	va_list ap;
101
	char **argv;
102
	int n;
103
104
	va_start(ap, arg);
105
	n = 1;
106
	while (va_arg(ap, char *) != NULL)
107
		n++;
108
	va_end(ap);
109
	argv = alloca((n + 1) * sizeof(*argv));
110
	if (argv == NULL) {
111
		errno = ENOMEM;
112
		return (-1);
113
	}
114
	va_start(ap, arg);
115
	n = 1;
116
	argv[0] = (char *)arg;
117
	while ((argv[n] = va_arg(ap, char *)) != NULL)
118
		n++;
119
	va_end(ap);
120
	return (execvp(name, argv));
121
}
122
123
int
124
execv(const char *name, char *const *argv)
125
{
126
	(void)execve(name, argv, environ);
127
	return (-1);
128
}
129
130
int
131
execvpe(const char *name, char *const *argv, char *const *envp)
132
{
133
	char **memp;
134
	int cnt;
135
	size_t lp, ln, len;
136
	char *p;
137
	int eacces = 0;
138
	char *bp, *cur, *path, buf[PATH_MAX];
139
140
	/*
141
	 * Do not allow null name
142
	 */
143
	if (name == NULL || *name == '\0') {
144
		errno = ENOENT;
145
		return (-1);
146
 	}
147
148
	/* If it's an absolute or relative path name, it's easy. */
149
	if (strchr(name, '/')) {
150
		bp = (char *)name;
151
		cur = path = NULL;
152
		goto retry;
153
	}
154
	bp = buf;
155
156
	/* Get the path we're searching. */
157
	if (!(path = getenv("PATH")))
158
		path = _PATH_DEFPATH;
159
	len = strlen(path) + 1;
160
	cur = alloca(len);
161
	if (cur == NULL) {
162
		errno = ENOMEM;
163
		return (-1);
164
	}
165
	strlcpy(cur, path, len);
166
	path = cur;
167
	while ((p = strsep(&cur, ":"))) {
168
		/*
169
		 * It's a SHELL path -- double, leading and trailing colons
170
		 * mean the current directory.
171
		 */
172
		if (!*p) {
173
			p = ".";
174
			lp = 1;
175
		} else
176
			lp = strlen(p);
177
		ln = strlen(name);
178
179
		/*
180
		 * If the path is too long complain.  This is a possible
181
		 * security issue; given a way to make the path too long
182
		 * the user may execute the wrong program.
183
		 */
184
		if (lp + ln + 2 > sizeof(buf)) {
185
			struct iovec iov[3];
186
187
			iov[0].iov_base = "execvp: ";
188
			iov[0].iov_len = 8;
189
			iov[1].iov_base = p;
190
			iov[1].iov_len = lp;
191
			iov[2].iov_base = ": path too long\n";
192
			iov[2].iov_len = 16;
193
			(void)writev(STDERR_FILENO, iov, 3);
194
			continue;
195
		}
196
		bcopy(p, buf, lp);
197
		buf[lp] = '/';
198
		bcopy(name, buf + lp + 1, ln);
199
		buf[lp + ln + 1] = '\0';
200
201
retry:		(void)execve(bp, argv, envp);
202
		switch(errno) {
203
		case E2BIG:
204
			goto done;
205
		case EISDIR:
206
		case ELOOP:
207
		case ENAMETOOLONG:
208
		case ENOENT:
209
			break;
210
		case ENOEXEC:
211
			for (cnt = 0; argv[cnt]; ++cnt)
212
				;
213
			memp = alloca((cnt + 2) * sizeof(char *));
214
			if (memp == NULL)
215
				goto done;
216
			memp[0] = "sh";
217
			memp[1] = bp;
218
			bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
219
			(void)execve(_PATH_BSHELL, memp, envp);
220
			goto done;
221
		case ENOMEM:
222
			goto done;
223
		case ENOTDIR:
224
			break;
225
		case ETXTBSY:
226
			/*
227
			 * We used to retry here, but sh(1) doesn't.
228
			 */
229
			goto done;
230
		case EACCES:
231
			eacces = 1;
232
			break;
233
		default:
234
			goto done;
235
		}
236
	}
237
	if (eacces)
238
		errno = EACCES;
239
	else if (!errno)
240
		errno = ENOENT;
241
done:
242
	return (-1);
243
}
244
DEF_WEAK(execvpe);
245
246
int
247
execvp(const char *name, char *const *argv)
248
{
249
    return execvpe(name, argv, environ);
250
}
251
DEF_WEAK(execvp);
252