no SCCS file; new copyright; att/bsd/shared
[unix-history] / usr / src / lib / libc / gen / exec.c
CommitLineData
468a338d
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
2ce81398 8#if defined(LIBC_SCCS) && !defined(lint)
57047b12 9static char sccsid[] = "@(#)exec.c 5.8 (Berkeley) %G%";
468a338d 10#endif /* LIBC_SCCS and not lint */
b8f253e8 11
468a338d
KB
12#include <sys/param.h>
13#include <sys/types.h>
a69e788c 14#include <errno.h>
468a338d 15#include <unistd.h>
c98aae91 16#include <stdlib.h>
e0cd943a 17#if __STDC__
468a338d 18#include <stdarg.h>
e0cd943a
DS
19#else
20#include <varargs.h>
21#endif
c98aae91 22#include <string.h>
468a338d
KB
23#include <stdio.h>
24#include <paths.h>
25
26extern char **environ;
27
e0cd943a
DS
28static char **
29buildargv(ap, arg, envpp)
30 va_list ap;
31 const char *arg;
32 char ***envpp;
468a338d
KB
33{
34 register size_t max, off;
0331f271 35 register char **argv = NULL;
468a338d
KB
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
e0cd943a
DS
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
468a338d
KB
66{
67 va_list ap;
68 int sverrno;
69 char **argv;
70
e0cd943a 71#if __STDC__
468a338d 72 va_start(ap, arg);
e0cd943a
DS
73#else
74 va_start(ap);
75#endif
468a338d
KB
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
e0cd943a
DS
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
468a338d
KB
94{
95 va_list ap;
96 int sverrno;
97 char **argv, **envp;
98
e0cd943a 99#if __STDC__
468a338d 100 va_start(ap, arg);
e0cd943a
DS
101#else
102 va_start(ap);
103#endif
468a338d
KB
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
e0cd943a
DS
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
468a338d
KB
122{
123 va_list ap;
124 int sverrno;
125 char **argv;
a69e788c 126
e0cd943a 127#if __STDC__
468a338d 128 va_start(ap, arg);
e0cd943a
DS
129#else
130 va_start(ap);
131#endif
468a338d
KB
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}
a69e788c 140
e0cd943a
DS
141int
142execv(name, argv)
143 const char *name;
144 char * const *argv;
a69e788c 145{
468a338d
KB
146 (void)execve(name, argv, environ);
147 return(-1);
a69e788c
BJ
148}
149
e0cd943a
DS
150int
151execvp(name, argv)
152 const char *name;
153 char * const *argv;
a69e788c 154{
468a338d
KB
155 register char *p;
156 int eacces, etxtbsy;
57047b12 157 char *bp, *cur, *path, buf[MAXPATHLEN];
468a338d
KB
158
159 /* If it's an absolute or relative path name, it's easy. */
160 if (index(name, '/')) {
57047b12
KB
161 bp = (char *)name;
162 cur = path = NULL;
163 goto retry;
468a338d 164 }
57047b12 165 bp = buf;
468a338d
KB
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
57047b12 182retry: (void)execve(bp, argv, environ);
a69e788c 183 switch(errno) {
468a338d
KB
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 *))) {
57047b12 195 bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
468a338d 196 ap[0] = "sh";
57047b12 197 ap[1] = bp;
468a338d
KB
198 (void)execve(_PATH_BSHELL, ap, environ);
199 free(ap);
a69e788c 200 }
468a338d
KB
201 goto done;
202 }
a69e788c 203 case ETXTBSY:
468a338d
KB
204 if (etxtbsy < 3)
205 (void)sleep(++etxtbsy);
a69e788c 206 goto retry;
468a338d
KB
207 default:
208 goto done;
a69e788c 209 }
468a338d 210 }
a69e788c
BJ
211 if (eacces)
212 errno = EACCES;
468a338d
KB
213 else if (!errno)
214 errno = ENOENT;
57047b12
KB
215done: if (path)
216 free(path);
a69e788c
BJ
217 return(-1);
218}