syscalls: implement argv and envp handling in execve
This commit is contained in:
+70
-3
@@ -18,6 +18,8 @@ extern void switchProcess(Process* next);
|
||||
|
||||
#define EBADF 9
|
||||
|
||||
#define EXECVE_MAX_ARGUMENT_SIZE 255
|
||||
|
||||
const char* flags_to_mode_str(int flags) {
|
||||
static char mode[4] = {0};
|
||||
int accmode = flags & 3;
|
||||
@@ -251,9 +253,44 @@ int sys_close(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) {
|
||||
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;
|
||||
int err = vsf_read_file_by_path(filename, &file_buffer, root_dir);
|
||||
if (err != 0) {
|
||||
@@ -304,10 +341,40 @@ int sys_execve(TrapFrame *tf) {
|
||||
void* phys_addr = alloc_page();
|
||||
map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
||||
}
|
||||
|
||||
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
|
||||
user_esp -= 4; *(uint32_t*)user_esp = 0; // argc
|
||||
|
||||
//push environment strings
|
||||
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);
|
||||
free(file_buffer);
|
||||
|
||||
Reference in New Issue
Block a user