170 lines
4 KiB
C
170 lines
4 KiB
C
|
#include <lib.h>
|
||
|
#include <string.h>
|
||
|
#define execl _execl
|
||
|
#define execle _execle
|
||
|
#define execv _execv
|
||
|
#define execve _execve
|
||
|
#include <unistd.h>
|
||
|
|
||
|
extern char **environ; /* environment pointer */
|
||
|
|
||
|
#define PTRSIZE (sizeof(char *))
|
||
|
_PROTOTYPE( char *_sbrk, (int _incr) );
|
||
|
|
||
|
#if _ANSI
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
PUBLIC int execl(char *name, ...)
|
||
|
{
|
||
|
int retval;
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, name);
|
||
|
retval = execve(name, (char **)ap, environ);
|
||
|
va_end(ap);
|
||
|
return retval;
|
||
|
}
|
||
|
#else
|
||
|
PUBLIC int execl(name, arg0)
|
||
|
char *name;
|
||
|
char *arg0;
|
||
|
{
|
||
|
return(execve(name, &arg0, environ));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if _ANSI
|
||
|
PUBLIC int execle(char *name, ...)
|
||
|
{
|
||
|
int retval;
|
||
|
va_list ap;
|
||
|
char *p;
|
||
|
|
||
|
va_start(ap, name);
|
||
|
do {
|
||
|
p = va_arg(ap, char *);
|
||
|
} while(p);
|
||
|
p = (char *)va_arg(ap, char **);
|
||
|
va_end(ap);
|
||
|
va_start(ap, name);
|
||
|
retval = execve(name, (char **)ap, (char **) p);
|
||
|
va_end(ap);
|
||
|
return retval;
|
||
|
}
|
||
|
#else
|
||
|
PUBLIC int execle(name, argv)
|
||
|
char *name, *argv;
|
||
|
{
|
||
|
char **p;
|
||
|
p = (char **) &argv;
|
||
|
while (*p++) /* null statement */
|
||
|
;
|
||
|
return(execve(name, &argv, (char **) *p));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
PUBLIC int execv(name, argv)
|
||
|
char *name, *argv[];
|
||
|
{
|
||
|
|
||
|
return(execve(name, argv, environ));
|
||
|
}
|
||
|
|
||
|
PUBLIC int execve(path, argv, envp)
|
||
|
char *path; /* pointer to name of file to be executed */
|
||
|
char *argv[]; /* pointer to argument array */
|
||
|
char *envp[]; /* pointer to environment */
|
||
|
{
|
||
|
register char **argtop;
|
||
|
register char **envtop;
|
||
|
|
||
|
/* Count the argument pointers and environment pointers. */
|
||
|
for (argtop = argv; *argtop != (char *) NULL; ) argtop++;
|
||
|
for (envtop = envp; *envtop != (char *) NULL; ) envtop++;
|
||
|
return(__execve(path, argv, envp, (int)(argtop - argv), (int)(envtop - envp)));
|
||
|
}
|
||
|
|
||
|
PUBLIC int __execve(path, argv, envp, nargs, nenvps)
|
||
|
char *path; /* pointer to name of file to be executed */
|
||
|
char *argv[]; /* pointer to argument array */
|
||
|
char *envp[]; /* pointer to environment */
|
||
|
int nargs; /* number of args */
|
||
|
int nenvps; /* number of environment strings */
|
||
|
{
|
||
|
/* This is split off from execve to be called from execvp, so execvp does not
|
||
|
* have to allocate up to ARG_MAX bytes just to prepend "sh" to the arg array.
|
||
|
*/
|
||
|
|
||
|
char *hp, **ap, *p;
|
||
|
int i, stackbytes, npointers, overflow, temp;
|
||
|
char *stack;
|
||
|
/* Decide how big a stack is needed. Be paranoid about overflow. */
|
||
|
#if ARG_MAX > INT_MAX
|
||
|
#error /* overflow checks and sbrk depend on sizes being ints */
|
||
|
#endif
|
||
|
overflow = FALSE;
|
||
|
npointers = 1 + nargs + 1 + nenvps + 1; /* 1's for argc and NULLs */
|
||
|
stackbytes = 0; /* changed because _len is used now */
|
||
|
if (nargs < 0 || nenvps < 0 || nargs+nenvps < 0 || npointers < 0)
|
||
|
overflow = TRUE;
|
||
|
for (i = PTRSIZE; i != 0; i--) {
|
||
|
temp = stackbytes + npointers;
|
||
|
if (temp < stackbytes) overflow = TRUE;
|
||
|
stackbytes = temp;
|
||
|
}
|
||
|
for (i = 0, ap = argv; i < nargs; i++) {
|
||
|
temp = stackbytes + _len(*ap++);
|
||
|
if (temp < stackbytes) overflow = TRUE;
|
||
|
stackbytes = temp;
|
||
|
}
|
||
|
for (i = 0, ap = envp; i < nenvps; i++) {
|
||
|
temp = stackbytes + _len(*ap++);
|
||
|
if (temp < stackbytes) overflow = TRUE;
|
||
|
stackbytes = temp;
|
||
|
}
|
||
|
temp = stackbytes + PTRSIZE - 1;
|
||
|
if (temp < stackbytes) overflow = TRUE;
|
||
|
stackbytes = (temp / PTRSIZE) * PTRSIZE;
|
||
|
|
||
|
/* Check for overflow before committing sbrk. */
|
||
|
if (overflow || stackbytes > ARG_MAX) {
|
||
|
errno = E2BIG;
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
/* Allocate the stack. */
|
||
|
stack = _sbrk(stackbytes);
|
||
|
if (stack == (char *) -1) {
|
||
|
errno = E2BIG;
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
/* Prepare the stack vector and argc. */
|
||
|
ap = (char **) stack;
|
||
|
hp = &stack[npointers * PTRSIZE];
|
||
|
*ap++ = (char *) nargs;
|
||
|
|
||
|
/* Prepare the argument pointers and strings. */
|
||
|
for (i = 0; i < nargs; i++) {
|
||
|
*ap++ = (char *) (hp - stack);
|
||
|
p = *argv++;
|
||
|
while ((*hp++ = *p++) != 0)
|
||
|
;
|
||
|
}
|
||
|
*ap++ = (char *) NULL;
|
||
|
|
||
|
/* Prepare the environment pointers and strings. */
|
||
|
for (i = 0; i < nenvps; i++) {
|
||
|
*ap++ = (char *) (hp - stack);
|
||
|
p = *envp++;
|
||
|
while ((*hp++ = *p++) != 0)
|
||
|
;
|
||
|
}
|
||
|
*ap++ = (char *) NULL;
|
||
|
|
||
|
/* Do the real work. */
|
||
|
temp = _callm1(MM, EXEC, _len(path), stackbytes, 0, path, stack, NIL_PTR);
|
||
|
_sbrk(-stackbytes);
|
||
|
return(temp);
|
||
|
}
|