168 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <lib.h>
 | |
| #include <unistd.h>
 | |
| #define execl	_execl
 | |
| #define execle	_execle
 | |
| #define execv	_execv
 | |
| #define execve	_execve
 | |
| 
 | |
| 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);
 | |
| }
 |