172db608eSbostic /*-
2*bac379f5Sbostic * Copyright (c) 1991, 1993
3*bac379f5Sbostic * The Regents of the University of California. All rights reserved.
472db608eSbostic *
572db608eSbostic * %sccs.include.redist.c%
6f8f88d12Swnj */
772db608eSbostic
872db608eSbostic #if defined(LIBC_SCCS) && !defined(lint)
9*bac379f5Sbostic static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 06/04/93";
1072db608eSbostic #endif /* LIBC_SCCS and not lint */
1172db608eSbostic
1272db608eSbostic #include <sys/param.h>
1372db608eSbostic #include <sys/types.h>
14f8f88d12Swnj #include <errno.h>
155ba59b7eSdonn #include <unistd.h>
1672db608eSbostic #include <stdlib.h>
17d37da86fSbostic #include <string.h>
18d37da86fSbostic #include <stdio.h>
19d37da86fSbostic #include <paths.h>
20d37da86fSbostic
219e1dd68bSdonn #if __STDC__
2272db608eSbostic #include <stdarg.h>
239e1dd68bSdonn #else
249e1dd68bSdonn #include <varargs.h>
259e1dd68bSdonn #endif
26f8f88d12Swnj
2772db608eSbostic extern char **environ;
28f8f88d12Swnj
299e1dd68bSdonn static char **
buildargv(ap,arg,envpp)309e1dd68bSdonn buildargv(ap, arg, envpp)
319e1dd68bSdonn va_list ap;
329e1dd68bSdonn const char *arg;
339e1dd68bSdonn char ***envpp;
34f8f88d12Swnj {
35208aaaf1Sbostic static int memsize;
36208aaaf1Sbostic static char **argv;
37208aaaf1Sbostic register int off;
38f8f88d12Swnj
39208aaaf1Sbostic argv = NULL;
40208aaaf1Sbostic for (off = 0;; ++off) {
41208aaaf1Sbostic if (off >= memsize) {
42208aaaf1Sbostic memsize += 50; /* Starts out at 0. */
43208aaaf1Sbostic memsize *= 2; /* Ramp up fast. */
44208aaaf1Sbostic if (!(argv = realloc(argv, memsize * sizeof(char *)))) {
45208aaaf1Sbostic memsize = 0;
4672db608eSbostic return (NULL);
47208aaaf1Sbostic }
4872db608eSbostic if (off == 0) {
4972db608eSbostic argv[0] = (char *)arg;
5072db608eSbostic off = 1;
51f8f88d12Swnj }
52f8f88d12Swnj }
5372db608eSbostic if (!(argv[off] = va_arg(ap, char *)))
54f8f88d12Swnj break;
5572db608eSbostic }
56d37da86fSbostic /* Get environment pointer if user supposed to provide one. */
5772db608eSbostic if (envpp)
5872db608eSbostic *envpp = va_arg(ap, char **);
5972db608eSbostic return (argv);
6072db608eSbostic }
6172db608eSbostic
629e1dd68bSdonn int
639e1dd68bSdonn #if __STDC__
execl(const char * name,const char * arg,...)649e1dd68bSdonn execl(const char *name, const char *arg, ...)
659e1dd68bSdonn #else
669e1dd68bSdonn execl(name, arg, va_alist)
679e1dd68bSdonn const char *name;
689e1dd68bSdonn const char *arg;
699e1dd68bSdonn va_dcl
709e1dd68bSdonn #endif
7172db608eSbostic {
7272db608eSbostic va_list ap;
7372db608eSbostic int sverrno;
7472db608eSbostic char **argv;
7572db608eSbostic
769e1dd68bSdonn #if __STDC__
7772db608eSbostic va_start(ap, arg);
789e1dd68bSdonn #else
799e1dd68bSdonn va_start(ap);
809e1dd68bSdonn #endif
81208aaaf1Sbostic if (argv = buildargv(ap, arg, NULL))
8272db608eSbostic (void)execve(name, argv, environ);
8372db608eSbostic va_end(ap);
8472db608eSbostic sverrno = errno;
8572db608eSbostic free(argv);
8672db608eSbostic errno = sverrno;
87f8f88d12Swnj return (-1);
88f8f88d12Swnj }
8972db608eSbostic
909e1dd68bSdonn int
919e1dd68bSdonn #if __STDC__
execle(const char * name,const char * arg,...)929e1dd68bSdonn execle(const char *name, const char *arg, ...)
939e1dd68bSdonn #else
949e1dd68bSdonn execle(name, arg, va_alist)
959e1dd68bSdonn const char *name;
969e1dd68bSdonn const char *arg;
979e1dd68bSdonn va_dcl
989e1dd68bSdonn #endif
9972db608eSbostic {
10072db608eSbostic va_list ap;
10172db608eSbostic int sverrno;
10272db608eSbostic char **argv, **envp;
10372db608eSbostic
1049e1dd68bSdonn #if __STDC__
10572db608eSbostic va_start(ap, arg);
1069e1dd68bSdonn #else
1079e1dd68bSdonn va_start(ap);
1089e1dd68bSdonn #endif
10972db608eSbostic if (argv = buildargv(ap, arg, &envp))
11072db608eSbostic (void)execve(name, argv, envp);
11172db608eSbostic va_end(ap);
11272db608eSbostic sverrno = errno;
11372db608eSbostic free(argv);
11472db608eSbostic errno = sverrno;
11572db608eSbostic return (-1);
11672db608eSbostic }
11772db608eSbostic
1189e1dd68bSdonn int
1199e1dd68bSdonn #if __STDC__
execlp(const char * name,const char * arg,...)1209e1dd68bSdonn execlp(const char *name, const char *arg, ...)
1219e1dd68bSdonn #else
1229e1dd68bSdonn execlp(name, arg, va_alist)
1239e1dd68bSdonn const char *name;
1249e1dd68bSdonn const char *arg;
1259e1dd68bSdonn va_dcl
1269e1dd68bSdonn #endif
12772db608eSbostic {
12872db608eSbostic va_list ap;
12972db608eSbostic int sverrno;
13072db608eSbostic char **argv;
13172db608eSbostic
1329e1dd68bSdonn #if __STDC__
13372db608eSbostic va_start(ap, arg);
1349e1dd68bSdonn #else
1359e1dd68bSdonn va_start(ap);
1369e1dd68bSdonn #endif
137208aaaf1Sbostic if (argv = buildargv(ap, arg, NULL))
13872db608eSbostic (void)execvp(name, argv);
13972db608eSbostic va_end(ap);
14072db608eSbostic sverrno = errno;
14172db608eSbostic free(argv);
14272db608eSbostic errno = sverrno;
14372db608eSbostic return (-1);
14472db608eSbostic }
14572db608eSbostic
1469e1dd68bSdonn int
execv(name,argv)1479e1dd68bSdonn execv(name, argv)
1489e1dd68bSdonn const char *name;
1499e1dd68bSdonn char * const *argv;
15072db608eSbostic {
15172db608eSbostic (void)execve(name, argv, environ);
15272db608eSbostic return (-1);
15372db608eSbostic }
15472db608eSbostic
1559e1dd68bSdonn int
execvp(name,argv)1569e1dd68bSdonn execvp(name, argv)
1579e1dd68bSdonn const char *name;
1589e1dd68bSdonn char * const *argv;
15972db608eSbostic {
160208aaaf1Sbostic static int memsize;
161208aaaf1Sbostic static char **memp;
162208aaaf1Sbostic register int cnt, lp, ln;
16372db608eSbostic register char *p;
16472db608eSbostic int eacces, etxtbsy;
1653c93bb12Sbostic char *bp, *cur, *path, buf[MAXPATHLEN];
16672db608eSbostic
16772db608eSbostic /* If it's an absolute or relative path name, it's easy. */
16872db608eSbostic if (index(name, '/')) {
1693c93bb12Sbostic bp = (char *)name;
1703c93bb12Sbostic cur = path = NULL;
1713c93bb12Sbostic goto retry;
17272db608eSbostic }
1733c93bb12Sbostic bp = buf;
17472db608eSbostic
17572db608eSbostic /* Get the path we're searching. */
17672db608eSbostic if (!(path = getenv("PATH")))
17772db608eSbostic path = _PATH_DEFPATH;
17872db608eSbostic cur = path = strdup(path);
17972db608eSbostic
18072db608eSbostic eacces = etxtbsy = 0;
18172db608eSbostic while (p = strsep(&cur, ":")) {
18272db608eSbostic /*
18372db608eSbostic * It's a SHELL path -- double, leading and trailing colons
18472db608eSbostic * mean the current directory.
18572db608eSbostic */
186d37da86fSbostic if (!*p) {
18772db608eSbostic p = ".";
188d37da86fSbostic lp = 1;
189d37da86fSbostic } else
190d37da86fSbostic lp = strlen(p);
191d37da86fSbostic ln = strlen(name);
192d37da86fSbostic
193d37da86fSbostic /*
194d37da86fSbostic * If the path is too long complain. This is a possible
195d37da86fSbostic * security issue; given a way to make the path too long
196d37da86fSbostic * the user may execute the wrong program.
197d37da86fSbostic */
198d37da86fSbostic if (lp + ln + 2 > sizeof(buf)) {
199d37da86fSbostic (void)write(STDERR_FILENO, "execvp: ", 8);
200d37da86fSbostic (void)write(STDERR_FILENO, p, lp);
201d37da86fSbostic (void)write(STDERR_FILENO, ": path too long\n", 16);
202d37da86fSbostic continue;
203d37da86fSbostic }
204d37da86fSbostic bcopy(p, buf, lp);
205d37da86fSbostic buf[lp] = '/';
206d37da86fSbostic bcopy(name, buf + lp + 1, ln);
207d37da86fSbostic buf[lp + ln + 1] = '\0';
20872db608eSbostic
2093c93bb12Sbostic retry: (void)execve(bp, argv, environ);
21072db608eSbostic switch(errno) {
21172db608eSbostic case EACCES:
21272db608eSbostic eacces = 1;
21372db608eSbostic break;
21472db608eSbostic case ENOENT:
21572db608eSbostic break;
216208aaaf1Sbostic case ENOEXEC:
217208aaaf1Sbostic for (cnt = 0; argv[cnt]; ++cnt);
218208aaaf1Sbostic if ((cnt + 2) * sizeof(char *) > memsize) {
219208aaaf1Sbostic memsize = (cnt + 2) * sizeof(char *);
220208aaaf1Sbostic if ((memp = realloc(memp, memsize)) == NULL) {
221208aaaf1Sbostic memsize = 0;
22272db608eSbostic goto done;
22372db608eSbostic }
224208aaaf1Sbostic }
225208aaaf1Sbostic memp[0] = "sh";
226208aaaf1Sbostic memp[1] = bp;
227208aaaf1Sbostic bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
228208aaaf1Sbostic (void)execve(_PATH_BSHELL, memp, environ);
229208aaaf1Sbostic goto done;
23072db608eSbostic case ETXTBSY:
23172db608eSbostic if (etxtbsy < 3)
23272db608eSbostic (void)sleep(++etxtbsy);
23372db608eSbostic goto retry;
23472db608eSbostic default:
23572db608eSbostic goto done;
23672db608eSbostic }
23772db608eSbostic }
238f8f88d12Swnj if (eacces)
239f8f88d12Swnj errno = EACCES;
24072db608eSbostic else if (!errno)
24172db608eSbostic errno = ENOENT;
2423c93bb12Sbostic done: if (path)
2433c93bb12Sbostic free(path);
244f8f88d12Swnj return (-1);
245f8f88d12Swnj }
246