retire BIOS_SEG and umap_bios
[minix3.git] / lib / libc / sys-minix / execve.c
blobdcb84373c613d0a9be4da288efefcbee6424d377
1 /* execve() - basic program execution call Author: Kees J. Bot
2 * 21 Jan 1994
3 */
4 #define _MINIX_SOURCE
6 #include <sys/cdefs.h>
7 #include "namespace.h"
8 #include <lib.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <stddef.h>
13 #include <sys/exec_elf.h>
15 #ifdef __weak_alias
16 __weak_alias(execve, _execve)
17 #endif
19 int execve(const char *path, char * const *argv, char * const *envp)
21 char * const *ap;
22 char * const *ep;
23 char *frame;
24 char **vp;
25 char *sp;
26 size_t argc;
27 int extra;
28 int vectors;
29 size_t frame_size;
30 size_t string_off;
31 size_t n;
32 int ov;
33 message m;
35 /* Assumptions: size_t and char *, it's all the same thing. */
37 /* Create a stack image that only needs to be patched up slightly
38 * by the kernel to be used for the process to be executed.
41 ov= 0; /* No overflow yet. */
42 frame_size= 0; /* Size of the new initial stack. */
43 string_off= 0; /* Offset to start of the strings. */
44 argc= 0; /* Argument count. */
46 for (ap= argv; *ap != NULL; ap++) {
47 n = sizeof(*ap) + strlen(*ap) + 1;
48 frame_size+= n;
49 if (frame_size < n) ov= 1;
50 string_off+= sizeof(*ap);
51 argc++;
54 for (ep= envp; *ep != NULL; ep++) {
55 n = sizeof(*ep) + strlen(*ep) + 1;
56 frame_size+= n;
57 if (frame_size < n) ov= 1;
58 string_off+= sizeof(*ap);
61 /* Add an argument count, two terminating nulls and
62 * space for the ELF aux vectors, that must come before
63 * (i.e. at a higher address) then the strings.
65 vectors = sizeof(argc) + sizeof(*ap) + sizeof(*ep) +
66 sizeof(AuxInfo) * PMEF_AUXVECTORS;
67 extra = vectors + PMEF_EXECNAMELEN1;
68 frame_size+= extra;
69 string_off+= extra;
71 /* Align. */
72 frame_size= (frame_size + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
74 /* The party is off if there is an overflow. */
75 if (ov || frame_size < 3 * sizeof(char *)) {
76 errno= E2BIG;
77 return -1;
80 /* Allocate space for the stack frame. */
81 if ((frame = (char *) sbrk(frame_size)) == (char *) -1) {
82 errno = E2BIG;
83 return -1;
86 /* Set arg count, init pointers to vector and string tables. */
87 * (size_t *) frame = argc;
88 vp = (char **) (frame + sizeof(argc));
89 sp = frame + string_off;
91 /* Load the argument vector and strings. */
92 for (ap= argv; *ap != NULL; ap++) {
93 *vp++= (char *) (sp - frame);
94 n= strlen(*ap) + 1;
95 memcpy(sp, *ap, n);
96 sp+= n;
98 *vp++= NULL;
100 /* Load the environment vector and strings. */
101 for (ep= envp; *ep != NULL; ep++) {
102 *vp++= (char *) (sp - frame);
103 n= strlen(*ep) + 1;
104 memcpy(sp, *ep, n);
105 sp+= n;
107 *vp++= NULL;
109 /* Padding. */
110 while (sp < frame + frame_size) *sp++= 0;
112 /* Clear unused message fields */
113 memset(&m, 0, sizeof(m));
115 /* We can finally make the system call. */
116 m.m1_i1 = strlen(path) + 1;
117 m.m1_i2 = frame_size;
118 m.m1_p1 = (char *) __UNCONST(path);
119 m.m1_p2 = frame;
121 /* Tell PM/VFS we have left space for the aux vectors
122 * and executable name
124 m.PMEXEC_FLAGS = PMEF_AUXVECTORSPACE | PMEF_EXECNAMESPACE1;
126 (void) _syscall(PM_PROC_NR, EXEC, &m);
128 /* Failure, return the memory used for the frame and exit. */
129 (void) sbrk(-frame_size);
130 return -1;