syscalls: implement argv and envp handling in execve
This commit is contained in:
+2
-2
@@ -9,10 +9,10 @@ int main() {
|
|||||||
|
|
||||||
// Arguments for the new program
|
// Arguments for the new program
|
||||||
// The first argument is conventionally the program name
|
// The first argument is conventionally the program name
|
||||||
char *argv[] = {NULL}; //{ "./callee", "first_arg", "second_arg", NULL };
|
char *argv[] = { "./callee", "first_arg", "second_arg", NULL };
|
||||||
|
|
||||||
// Environment variables for the new program
|
// Environment variables for the new program
|
||||||
char *envp[] = {NULL}; //{ "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL };
|
char *envp[] = { "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL };
|
||||||
|
|
||||||
// The execve system call
|
// The execve system call
|
||||||
// The first argument is the path to the executable
|
// The first argument is the path to the executable
|
||||||
|
|||||||
+70
-3
@@ -18,6 +18,8 @@ extern void switchProcess(Process* next);
|
|||||||
|
|
||||||
#define EBADF 9
|
#define EBADF 9
|
||||||
|
|
||||||
|
#define EXECVE_MAX_ARGUMENT_SIZE 255
|
||||||
|
|
||||||
const char* flags_to_mode_str(int flags) {
|
const char* flags_to_mode_str(int flags) {
|
||||||
static char mode[4] = {0};
|
static char mode[4] = {0};
|
||||||
int accmode = flags & 3;
|
int accmode = flags & 3;
|
||||||
@@ -251,9 +253,44 @@ int sys_close(TrapFrame *tf)
|
|||||||
|
|
||||||
extern void execve_return(TrapFrame *tf);
|
extern void execve_return(TrapFrame *tf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this might be a not really good implementation as it only supports
|
||||||
|
* up to EXECVE_MAX_ARGUMENT_SIZE characters in each argument or environment
|
||||||
|
* string and for some reason I was unable to use malloc for kernel_argv and
|
||||||
|
* kernel_envp
|
||||||
|
*/
|
||||||
int sys_execve(TrapFrame *tf) {
|
int sys_execve(TrapFrame *tf) {
|
||||||
const char* filename = (const char*)tf->ebx;
|
const char* filename = (const char*)tf->ebx;
|
||||||
|
|
||||||
|
char **argv = (char**)tf->ecx;
|
||||||
|
char **envp = (char**)tf->edx;
|
||||||
|
|
||||||
|
int argc = 0;
|
||||||
|
int envc = 0;
|
||||||
|
|
||||||
|
while(argv[argc] != NULL)
|
||||||
|
{
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
|
while(envp[envc] != NULL)
|
||||||
|
{
|
||||||
|
envc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: check why was there a triple fault when I tried using malloc
|
||||||
|
char kernel_argv[argc][EXECVE_MAX_ARGUMENT_SIZE];
|
||||||
|
char kernel_envp[envc][EXECVE_MAX_ARGUMENT_SIZE];
|
||||||
|
|
||||||
|
for(int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
strcpy(kernel_argv[i], argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < envc; i++)
|
||||||
|
{
|
||||||
|
strcpy(kernel_envp[i], envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* file_buffer;
|
uint8_t* file_buffer;
|
||||||
int err = vsf_read_file_by_path(filename, &file_buffer, root_dir);
|
int err = vsf_read_file_by_path(filename, &file_buffer, root_dir);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
@@ -304,10 +341,40 @@ int sys_execve(TrapFrame *tf) {
|
|||||||
void* phys_addr = alloc_page();
|
void* phys_addr = alloc_page();
|
||||||
map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t user_esp = USER_STACK_TOP;
|
uint32_t user_esp = USER_STACK_TOP;
|
||||||
user_esp -= 4; *(uint32_t*)user_esp = 0; // envp
|
|
||||||
user_esp -= 4; *(uint32_t*)user_esp = 0; // argv
|
//push environment strings
|
||||||
user_esp -= 4; *(uint32_t*)user_esp = 0; // argc
|
uint32_t envp_pointers[envc + 1];
|
||||||
|
for (int i = envc - 1; i >= 0; i--) {
|
||||||
|
size_t len = strlen(kernel_envp[i]) + 1;
|
||||||
|
user_esp -= len;
|
||||||
|
memcpy((void*)user_esp, kernel_envp[i], len);
|
||||||
|
envp_pointers[i] = user_esp;
|
||||||
|
}
|
||||||
|
envp_pointers[envc] = 0;//null terminator
|
||||||
|
|
||||||
|
//push argument strings
|
||||||
|
uint32_t argv_pointers[argc + 1];
|
||||||
|
for (int i = argc - 1; i >= 0; i--) {
|
||||||
|
size_t len = strlen(kernel_argv[i]) + 1;
|
||||||
|
user_esp -= len;
|
||||||
|
memcpy((void*)user_esp, kernel_argv[i], len);
|
||||||
|
argv_pointers[i] = user_esp;
|
||||||
|
}
|
||||||
|
argv_pointers[argc] = 0;//null terminator
|
||||||
|
|
||||||
|
//push envp pointers
|
||||||
|
user_esp -= (envc + 1) * sizeof(uint32_t);
|
||||||
|
memcpy((void*)user_esp, envp_pointers, (envc + 1) * sizeof(uint32_t));
|
||||||
|
|
||||||
|
//push argv pointers
|
||||||
|
user_esp -= (argc + 1) * sizeof(uint32_t);
|
||||||
|
memcpy((void*)user_esp, argv_pointers, (argc + 1) * sizeof(uint32_t));
|
||||||
|
|
||||||
|
//push argc
|
||||||
|
user_esp -= sizeof(uint32_t);
|
||||||
|
*((uint32_t*)user_esp) = argc;
|
||||||
|
|
||||||
current->brk = (void*)(DivRoundUp(highest_vaddr, PAGE_SIZE) * PAGE_SIZE);
|
current->brk = (void*)(DivRoundUp(highest_vaddr, PAGE_SIZE) * PAGE_SIZE);
|
||||||
free(file_buffer);
|
free(file_buffer);
|
||||||
|
|||||||
Reference in New Issue
Block a user