116 lines
2.6 KiB
C
116 lines
2.6 KiB
C
|
/* execve() - basic program execution call Author: Kees J. Bot
|
||
|
* 21 Jan 1994
|
||
|
*/
|
||
|
|
||
|
#define _MINIX_SOURCE
|
||
|
|
||
|
#define nil 0
|
||
|
#define execve _execve
|
||
|
#define sbrk _sbrk
|
||
|
#include <lib.h>
|
||
|
#include <unistd.h>
|
||
|
#include <string.h>
|
||
|
#include <stddef.h>
|
||
|
|
||
|
int execve(const char *path, char * const *argv, char * const *envp)
|
||
|
{
|
||
|
char * const *ap;
|
||
|
char * const *ep;
|
||
|
char *frame;
|
||
|
char **vp;
|
||
|
char *sp;
|
||
|
size_t argc;
|
||
|
size_t frame_size;
|
||
|
size_t string_off;
|
||
|
size_t n;
|
||
|
int ov;
|
||
|
message m;
|
||
|
|
||
|
/* Assumptions: size_t and char *, it's all the same thing. */
|
||
|
|
||
|
/* Create a stack image that only needs to be patched up slightly
|
||
|
* by the kernel to be used for the process to be executed.
|
||
|
*/
|
||
|
|
||
|
ov= 0; /* No overflow yet. */
|
||
|
frame_size= 0; /* Size of the new initial stack. */
|
||
|
string_off= 0; /* Offset to start of the strings. */
|
||
|
argc= 0; /* Argument count. */
|
||
|
|
||
|
for (ap= argv; *ap != nil; ap++) {
|
||
|
n = sizeof(*ap) + strlen(*ap) + 1;
|
||
|
frame_size+= n;
|
||
|
if (frame_size < n) ov= 1;
|
||
|
string_off+= sizeof(*ap);
|
||
|
argc++;
|
||
|
}
|
||
|
|
||
|
for (ep= envp; *ep != nil; ep++) {
|
||
|
n = sizeof(*ep) + strlen(*ep) + 1;
|
||
|
frame_size+= n;
|
||
|
if (frame_size < n) ov= 1;
|
||
|
string_off+= sizeof(*ap);
|
||
|
}
|
||
|
|
||
|
/* Add an argument count and two terminating nulls. */
|
||
|
frame_size+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
|
||
|
string_off+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
|
||
|
|
||
|
/* Align. */
|
||
|
frame_size= (frame_size + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
|
||
|
|
||
|
/* The party is off if there is an overflow. */
|
||
|
if (ov || frame_size < 3 * sizeof(char *)) {
|
||
|
errno= E2BIG;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* Allocate space for the stack frame. */
|
||
|
if ((frame = (char *) sbrk(frame_size)) == (char *) -1) {
|
||
|
errno = E2BIG;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* Set arg count, init pointers to vector and string tables. */
|
||
|
* (size_t *) frame = argc;
|
||
|
vp = (char **) (frame + sizeof(argc));
|
||
|
sp = frame + string_off;
|
||
|
|
||
|
/* Load the argument vector and strings. */
|
||
|
for (ap= argv; *ap != nil; ap++) {
|
||
|
*vp++= (char *) (sp - frame);
|
||
|
n= strlen(*ap) + 1;
|
||
|
memcpy(sp, *ap, n);
|
||
|
sp+= n;
|
||
|
}
|
||
|
*vp++= nil;
|
||
|
|
||
|
/* Load the environment vector and strings. */
|
||
|
for (ep= envp; *ep != nil; ep++) {
|
||
|
*vp++= (char *) (sp - frame);
|
||
|
n= strlen(*ep) + 1;
|
||
|
memcpy(sp, *ep, n);
|
||
|
sp+= n;
|
||
|
}
|
||
|
*vp++= nil;
|
||
|
|
||
|
/* Padding. */
|
||
|
while (sp < frame + frame_size) *sp++= 0;
|
||
|
|
||
|
/* We can finally make the system call. */
|
||
|
m.m1_i1 = strlen(path) + 1;
|
||
|
m.m1_i2 = frame_size;
|
||
|
m.m1_p1 = (char *) path;
|
||
|
m.m1_p2 = frame;
|
||
|
|
||
|
/* Clear unused fields */
|
||
|
m.m1_i3 = 0;
|
||
|
m.m1_p3 = NULL;
|
||
|
|
||
|
(void) _syscall(MM, EXEC, &m);
|
||
|
|
||
|
/* Failure, return the memory used for the frame and exit. */
|
||
|
(void) sbrk(-frame_size);
|
||
|
return -1;
|
||
|
}
|