date and time created 91/04/12 13:40:37 by bostic
[unix-history] / usr / src / lib / libc / gen / exec.c
... / ...
CommitLineData
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#if defined(LIBC_SCCS) && !defined(lint)
9static char sccsid[] = "@(#)exec.c 5.8 (Berkeley) %G%";
10#endif /* LIBC_SCCS and not lint */
11
12#include <sys/param.h>
13#include <sys/types.h>
14#include <errno.h>
15#include <unistd.h>
16#include <stdlib.h>
17#if __STDC__
18#include <stdarg.h>
19#else
20#include <varargs.h>
21#endif
22#include <string.h>
23#include <stdio.h>
24#include <paths.h>
25
26extern char **environ;
27
28static char **
29buildargv(ap, arg, envpp)
30 va_list ap;
31 const char *arg;
32 char ***envpp;
33{
34 register size_t max, off;
35 register char **argv = NULL;
36
37 for (off = max = 0;; ++off) {
38 if (off >= max) {
39 max += 50; /* Starts out at 0. */
40 max *= 2; /* Ramp up fast. */
41 if (!(argv = realloc(argv, max * sizeof(char *))))
42 return(NULL);
43 if (off == 0) {
44 argv[0] = (char *)arg;
45 off = 1;
46 }
47 }
48 if (!(argv[off] = va_arg(ap, char *)))
49 break;
50 }
51 /* Get environment pointer if need user supposed to provide one. */
52 if (envpp)
53 *envpp = va_arg(ap, char **);
54 return(argv);
55}
56
57int
58#if __STDC__
59execl(const char *name, const char *arg, ...)
60#else
61execl(name, arg, va_alist)
62 const char *name;
63 const char *arg;
64 va_dcl
65#endif
66{
67 va_list ap;
68 int sverrno;
69 char **argv;
70
71#if __STDC__
72 va_start(ap, arg);
73#else
74 va_start(ap);
75#endif
76 if (argv = buildargv(ap, arg, (char ***)NULL))
77 (void)execve(name, argv, environ);
78 va_end(ap);
79 sverrno = errno;
80 free(argv);
81 errno = sverrno;
82 return(-1);
83}
84
85int
86#if __STDC__
87execle(const char *name, const char *arg, ...)
88#else
89execle(name, arg, va_alist)
90 const char *name;
91 const char *arg;
92 va_dcl
93#endif
94{
95 va_list ap;
96 int sverrno;
97 char **argv, **envp;
98
99#if __STDC__
100 va_start(ap, arg);
101#else
102 va_start(ap);
103#endif
104 if (argv = buildargv(ap, arg, &envp))
105 (void)execve(name, argv, envp);
106 va_end(ap);
107 sverrno = errno;
108 free(argv);
109 errno = sverrno;
110 return(-1);
111}
112
113int
114#if __STDC__
115execlp(const char *name, const char *arg, ...)
116#else
117execlp(name, arg, va_alist)
118 const char *name;
119 const char *arg;
120 va_dcl
121#endif
122{
123 va_list ap;
124 int sverrno;
125 char **argv;
126
127#if __STDC__
128 va_start(ap, arg);
129#else
130 va_start(ap);
131#endif
132 if (argv = buildargv(ap, arg, (char ***)NULL))
133 (void)execvp(name, argv);
134 va_end(ap);
135 sverrno = errno;
136 free(argv);
137 errno = sverrno;
138 return(-1);
139}
140
141int
142execv(name, argv)
143 const char *name;
144 char * const *argv;
145{
146 (void)execve(name, argv, environ);
147 return(-1);
148}
149
150int
151execvp(name, argv)
152 const char *name;
153 char * const *argv;
154{
155 register char *p;
156 int eacces, etxtbsy;
157 char *bp, *cur, *path, buf[MAXPATHLEN];
158
159 /* If it's an absolute or relative path name, it's easy. */
160 if (index(name, '/')) {
161 bp = (char *)name;
162 cur = path = NULL;
163 goto retry;
164 }
165 bp = buf;
166
167 /* Get the path we're searching. */
168 if (!(path = getenv("PATH")))
169 path = _PATH_DEFPATH;
170 cur = path = strdup(path);
171
172 eacces = etxtbsy = 0;
173 while (p = strsep(&cur, ":")) {
174 /*
175 * It's a SHELL path -- double, leading and trailing colons
176 * mean the current directory.
177 */
178 if (!*p)
179 p = ".";
180 (void)snprintf(buf, sizeof(buf), "%s/%s", p, name);
181
182retry: (void)execve(bp, argv, environ);
183 switch(errno) {
184 case EACCES:
185 eacces = 1;
186 break;
187 case ENOENT:
188 break;
189 case ENOEXEC: {
190 register size_t cnt;
191 register char **ap;
192
193 for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
194 if (ap = malloc((cnt + 2) * sizeof(char *))) {
195 bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
196 ap[0] = "sh";
197 ap[1] = bp;
198 (void)execve(_PATH_BSHELL, ap, environ);
199 free(ap);
200 }
201 goto done;
202 }
203 case ETXTBSY:
204 if (etxtbsy < 3)
205 (void)sleep(++etxtbsy);
206 goto retry;
207 default:
208 goto done;
209 }
210 }
211 if (eacces)
212 errno = EACCES;
213 else if (!errno)
214 errno = ENOENT;
215done: if (path)
216 free(path);
217 return(-1);
218}