#include <sys/param.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <paths.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#if defined(__APPLE__)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
int
#ifdef __STDC__
execl(const char *name, const char *arg, ...)
#else
execl(name, arg, va_alist)
const char *name;
const char *arg;
va_dcl
#endif
{
va_list ap;
char **argv;
int n;
#ifdef __STDC__
va_start(ap, arg);
#else
va_start(ap);
#endif
n = 1;
while (va_arg(ap, char *) != NULL)
n++;
va_end(ap);
argv = alloca((n + 1) * sizeof(*argv));
if (argv == NULL) {
errno = ENOMEM;
return (-1);
}
#ifdef __STDC__
va_start(ap, arg);
#else
va_start(ap);
#endif
n = 1;
argv[0] = (char *)arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
va_end(ap);
return (execve(name, argv, environ));
}
int
#ifdef __STDC__
execle(const char *name, const char *arg, ...)
#else
execle(name, arg, va_alist)
const char *name;
const char *arg;
va_dcl
#endif
{
va_list ap;
char **argv, **envp;
int n;
#ifdef __STDC__
va_start(ap, arg);
#else
va_start(ap);
#endif
n = 1;
while (va_arg(ap, char *) != NULL)
n++;
va_end(ap);
argv = alloca((n + 1) * sizeof(*argv));
if (argv == NULL) {
errno = ENOMEM;
return (-1);
}
#ifdef __STDC__
va_start(ap, arg);
#else
va_start(ap);
#endif
n = 1;
argv[0] = (char *)arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
envp = va_arg(ap, char **);
va_end(ap);
return (execve(name, argv, envp));
}
int
#ifdef __STDC__
execlp(const char *name, const char *arg, ...)
#else
execlp(name, arg, va_alist)
const char *name;
const char *arg;
va_dcl
#endif
{
va_list ap;
char **argv;
int n;
#ifdef __STDC__
va_start(ap, arg);
#else
va_start(ap);
#endif
n = 1;
while (va_arg(ap, char *) != NULL)
n++;
va_end(ap);
argv = alloca((n + 1) * sizeof(*argv));
if (argv == NULL) {
errno = ENOMEM;
return (-1);
}
#ifdef __STDC__
va_start(ap, arg);
#else
va_start(ap);
#endif
n = 1;
argv[0] = (char *)arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
va_end(ap);
return (execvp(name, argv));
}
int
execv(name, argv)
const char *name;
char * const *argv;
{
(void)execve(name, argv, environ);
return (-1);
}
int
execvp(name, argv)
const char *name;
char * const *argv;
{
char **memp;
register int cnt, lp, ln;
register char *p;
int eacces = 0, etxtbsy = 0;
char *bp, *cur, *path, buf[MAXPATHLEN];
if (name == NULL || *name == '\0') {
errno = ENOENT;
return (-1);
}
if (strchr(name, '/')) {
bp = (char *)name;
cur = path = NULL;
goto retry;
}
bp = buf;
if (!(path = getenv("PATH")))
path = _PATH_DEFPATH;
cur = alloca(strlen(path) + 1);
if (cur == NULL) {
errno = ENOMEM;
return (-1);
}
strcpy(cur, path);
path = cur;
while ((p = strsep(&cur, ":"))) {
if (!*p) {
p = ".";
lp = 1;
} else
lp = strlen(p);
ln = strlen(name);
if (lp + ln + 2 > sizeof(buf)) {
struct iovec iov[3];
iov[0].iov_base = "execvp: ";
iov[0].iov_len = 8;
iov[1].iov_base = p;
iov[1].iov_len = lp;
iov[2].iov_base = ": path too long\n";
iov[2].iov_len = 16;
(void)writev(STDERR_FILENO, iov, 3);
continue;
}
bcopy(p, buf, lp);
buf[lp] = '/';
bcopy(name, buf + lp + 1, ln);
buf[lp + ln + 1] = '\0';
retry: (void)execve(bp, argv, environ);
switch(errno) {
case E2BIG:
goto done;
case ELOOP:
case ENAMETOOLONG:
case ENOENT:
break;
case ENOEXEC:
for (cnt = 0; argv[cnt]; ++cnt)
;
memp = alloca((cnt + 2) * sizeof(char *));
if (memp == NULL)
goto done;
memp[0] = "sh";
memp[1] = bp;
bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
(void)execve(_PATH_BSHELL, memp, environ);
goto done;
case ENOMEM:
goto done;
case ENOTDIR:
break;
case ETXTBSY:
goto done;
case EACCES:
eacces = 1;
break;
default:
goto done;
}
}
if (eacces)
errno = EACCES;
else if (!errno)
errno = ENOENT;
done:
return (-1);
}