int runprogram(char *progname) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ #if OPT_A3 as = as_create(progname); #else as = as_create(); #endif if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } curthread->t_filetable = filetable_create(); if(curthread->t_filetable == NULL){ return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } //kprintf("\n in runprogram"); assignPid(); /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /* Warp to user mode. */ md_usermode(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **argv, unsigned long argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; pid_t pidRetVal; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create filetable for process*/ curthread->ft = create_process_filetable(); if(curthread->ft == NULL) { vfs_close(v); return ENOMEM; } /* Initialize STDIN, STDOUT, STDERR */ struct ft_node* standardIn = create_ft_node(); struct ft_node* standardOut = create_ft_node(); struct ft_node* standardErr = create_ft_node(); char console1[] = "con:"; result = vfs_open(console1, O_RDONLY, &standardIn->v); if(result) { kprintf("Cannot open STDIN\n"); vfs_close(v); return result; } standardIn->mode = O_RDONLY; array_add(curthread->ft->file_descriptors, standardIn); char console2[] = "con:"; result = vfs_open(console2, O_WRONLY, &standardOut->v); if(result) { kprintf("Cannot open STDOUT\n"); vfs_close(v); return result; } standardOut->mode = O_WRONLY; array_add(curthread->ft->file_descriptors, standardOut); char console3[] = "con:"; result = vfs_open(console3, O_WRONLY, &standardErr->v); if(result) { kprintf("Cannot open STDERR\n"); vfs_close(v); return result; } standardErr->mode = O_WRONLY; array_add(curthread->ft->file_descriptors, standardErr); /* Allocate initial PID for this first program */ result = allocate_pid(&pidRetVal); if(result) { kprintf("Could not allocate PID\n"); vfs_close(v); return result; } curthread->PID = pidRetVal; ((struct p_node *)array_getguy(pid_table, curthread->PID))->is_interested = 0; /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } //kprintf("finished loadelf in runprog\n"); /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } vaddr_t stackptrv[argc+1]; int i; size_t actual; for(i = argc-1; i >= 0; i--) { int len = strlen(argv[i]); len++; int padding = len % 4; stackptr -= len + (4 - padding); result = copyoutstr(argv[i], (userptr_t)stackptr, len, &actual); if(result) { return result; } stackptrv[i] = stackptr; } stackptrv[argc] = 0; for(i = argc; i >= 0; i--) { stackptr -= sizeof(vaddr_t); result = copyout(&stackptrv[i], (userptr_t)stackptr, sizeof(vaddr_t)); if(result) { return result; } } //kprintf("Before usernmode\n"); /* Warp to user mode. */ md_usermode(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(char* progname, char** args){ struct vnode *v; vaddr_t stackptr, entrypoint; int result; int string_size = 0; //s_size int kargc = 0; //kargc int err; char ** kernel_args; //kargs size_t check; //tt //CHECKS BEFORE WE BEGIN!! if(args == NULL) return EFAULT; if(progname == NULL) return ENOEXEC; struct addrspace* temp =(struct addrspace*)kmalloc(sizeof(struct addrspace)); if(temp == NULL) return ENOMEM; while(args[kargc] != NULL){ kargc++; } //Copy the address space to the one on the kernel heap. err = as_copy(curthread->t_vmspace, &(temp)); //If there is an error on copy. if(err){ kfree(temp); return ENOMEM; } //make a copy of the kernel args on the heap. kernel_args = (char **)kmalloc((kargc)*sizeof(char*)); if(kernel_args == NULL){ kfree(kernel_args); return ENOMEM; } int i,j; //Transfer the items passed in to the kernel heap array. for(i = 0; i<kargc; i++){ string_size = strlen(args[i]); kernel_args[i] =(char *)kmalloc(string_size * sizeof(char)); //If there is not enough memory... if(kernel_args[i]== NULL){ kfree(temp); for(j =0; j<i; j++){ kfree(kernel_args[j]); } kfree(kernel_args); return ENOMEM; } //If we get here, we have successfully copied the arguments. Copy in now. err = copyinstr(args[i], kernel_args[i], string_size+1, &check); //Check if copyinstr Success/Fail if(err){ for(i = 0; i<kargc; i++){ kfree(kernel_args[i]); } kfree(temp); kfree(kernel_args); return err; } } kernel_args[kargc]= NULL; //NOW, WE FOLLOW THE SAME PROCEDURE AS RUNPROGRAM!! /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { kfree(temp); for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); return result; } //Destroy the old address space, and setup the new one! as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; //Setup new vmspace. curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); vfs_close(v); return ENOMEM; } /* Activate vmspace */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); //We now prepare the user stack by placing the arguments on it, like we did in runprogram. result = as_define_stack(curthread->t_vmspace, &stackptr); //If error: if (result) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); return result; } // new addr space user stack vaddr_t new_args[kargc]; int padding; /*place all the strings on the stack*/ for(i = (kargc-1); i>=0 ; i--){ string_size = strlen(kernel_args[i]); padding = ((string_size / 4 ) + 1)*4; stackptr = stackptr - padding; //Do a copyout and check if success/fail err = copyoutstr(kernel_args[i], stackptr, string_size+1, &check); if(err){ return err; } //Success! new_args[i] = stackptr; } new_args[kargc] = NULL; for(i = kargc-1; i>=0 ; i--){ stackptr= stackptr- 4; err = copyout(&(new_args[i]), stackptr, 4); if(err){ return err; } } for(i =0; i<kargc; i++){ kfree(kernel_args[i]); } kfree(temp); kfree(kernel_args); /* Warp to user mode. */ md_usermode(kargc, stackptr, stackptr, entrypoint); }
int sys_execv(char* progname, char** args, int *retval, bool iskernel) { int result; int *args_len; size_t len; size_t total_len = 0; char *temp; char **kern_args; int nargs = 0; userptr_t *usr_argv = NULL; char *kern_progname = kmalloc(PATH_MAX); args_len = kmalloc(sizeof(int) * ARG_MAX); temp = kmalloc(sizeof(char) * ARG_MAX); if (kern_progname == NULL || args_len == NULL || temp == NULL){ *retval = -1; return ENOMEM; } if (args == NULL || progname == NULL) { *retval = -1; return EFAULT; } if (!iskernel) { result = copyinstr((userptr_t)args, temp, ARG_MAX, &len); if (result) { *retval = -1; return result; } } // Figure out nargs, and the length for each arg string while(args[nargs] != NULL) { if (iskernel) { len = strlen(args[nargs]) + 1; if (len == 1) { nargs--; break; } strcpy(temp, args[nargs]); } else { result = copyinstr((userptr_t)args[nargs], temp, ARG_MAX, &len); if (result) { *retval = -1; return result; } } args_len[nargs] = len; total_len += len; nargs += 1; } kfree(temp); if (total_len > ARG_MAX) { *retval = -1; return E2BIG; } kern_args = kmalloc(sizeof(char*) * nargs); // Go through args and copy everything over to kern_args using copyinstr for (int i = 0; i < nargs; i++) { kern_args[i] = kmalloc(sizeof(char) * args_len[i]); if (kern_args[i] == NULL) { *retval = -1; return ENOMEM; } if (iskernel) { strcpy(kern_args[i], args[i]); len = strlen(kern_args[i]); } else { copyinstr((userptr_t)args[i], kern_args[i], ARG_MAX, NULL); } } // This is from runprogram struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; if (iskernel) { strcpy(kern_progname, progname); len = strlen(kern_progname); } else { result = copyinstr((userptr_t)progname, kern_progname, PATH_MAX, NULL); } if (*kern_progname == 0) { *retval = -1; return EISDIR; } if (result) { kfree(kern_progname); *retval = -1; return result; } /* Open the file. */ result = vfs_open(kern_progname, O_RDONLY, 0, &v); if (result) { *retval = -1; return result; } // Blow up the current addrspace. TODO, this may be problematic if (!iskernel) { as_destroy(curproc->p_addrspace); curproc->p_addrspace = NULL; } /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { vfs_close(v); *retval = -1; return ENOMEM; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Intialize file table, not needed for execv */ if (iskernel) filetable_init(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); *retval = -1; return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ *retval = -1; return result; } // Clear space for arg pointers +1 for NULL terminator stackptr -= (sizeof(char*)) * (nargs + 1); // Convenience method for indexing usr_argv = (userptr_t*)stackptr; for(int i = 0; i < nargs; i++ ) { // Clear out space for an arg string stackptr -= sizeof(char) * (strlen(kern_args[i]) + 1); // Assign the string's pointer to usr_argv usr_argv[i] = (userptr_t)stackptr; // Copy over string copyout(kern_args[i], usr_argv[i], sizeof(char) * (strlen(kern_args[i]) + 1)); } // NULL terminate usr_argv usr_argv[nargs] = NULL; // Free memory for(int i = 0; i < nargs; i++) { kfree(kern_args[i]); } kfree(kern_args); /* Warp to user mode. */ enter_new_process(nargs /*argc*/, (userptr_t)usr_argv /*userspace addr of argv*/, NULL /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, int argc, char** args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } /* Initialize an array of pointers that stores the pointer to the * string arguments in the user stack */ char** argv = (char **)kmalloc((argc + 1) * sizeof(char*)); if (argv == NULL) { return ENOMEM; } argv[argc] = 0; int i; size_t actual; int total = 0; /* Copy string arguments from kernel memory onto the user stack, * and store the user pointer to the argument in argv */ for (i = argc - 1; i >= 0; i--) { int len = strlen(args[i]) + 1; total = total + len; stackptr = stackptr - len; copyoutstr(args[i], (userptr_t)stackptr, len, &actual); argv[i] = (char *)stackptr; } /* Add any necessary padding to the user stack */ int padding = 4 - (total % 4); if (padding) { stackptr = stackptr - padding; } /* Copy the array of user pointers argv onto the user stack */ for (i = argc; i >= 0; i--) { stackptr = stackptr - 4; copyout(&argv[i], (userptr_t)stackptr, 4); } kfree(argv); /* Warp to user mode. */ enter_new_process(argc, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, unsigned int nargs) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; int argc = nargs; char **argv = (char **)kmalloc((argc + 1) * sizeof(char *)); if(argv == NULL) { return ENOMEM; } for(int i = 0; i < argc; ++i) { argv[i] = args[i]; } argv[argc] = NULL; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } /*------copy args to user stack-----------*/ vaddr_t *argPtrs = (vaddr_t *)kmalloc((argc + 1) * sizeof(vaddr_t)); if(argPtrs == NULL) { for(int i = 0; i < argc; ++i) { kfree(argv[i]); } kfree(argv); as_deactivate(); as = curproc_setas(NULL); as_destroy(as); return ENOMEM; } for(int i = argc-1; i >= 0; --i) { //arg length with null size_t curArgLen = strlen(argv[i]) + 1; size_t argLen = ROUNDUP(curArgLen,4); stackptr -= (argLen * sizeof(char)); //kprintf("copying arg: %s to addr: %p\n", temp, (void *)stackptr); //copy to stack result = copyout((void *) argv[i], (userptr_t)stackptr, curArgLen); if(result) { kfree(argPtrs); for(int i = 0; i < argc; ++i) { kfree(argv[i]); } kfree(argv); as_deactivate(); as = curproc_setas(NULL); as_destroy(as); return result; } argPtrs[i] = stackptr; } argPtrs[argc] = (vaddr_t)NULL; //copy arg pointers for(int i = argc; i >= 0; --i) { stackptr -= sizeof(vaddr_t); result = copyout((void *) &argPtrs[i], ((userptr_t)stackptr),sizeof(vaddr_t)); if(result) { kfree(argPtrs); for(int i = 0; i < argc; ++i) { kfree(argv[i]); } kfree(argv); as_deactivate(); as = curproc_setas(NULL); as_destroy(as); return result; } } kfree(argPtrs); vaddr_t baseAddress = USERSTACK; vaddr_t argvPtr = stackptr; vaddr_t offset = ROUNDUP(USERSTACK - stackptr,8); stackptr = baseAddress - offset; /* for(vaddr_t i = baseAddress; i >= stackptr; --i) { char *temp; temp = (char *)i; //kprintf("%p: %c\n",(void *)i,*temp); kprintf("%p: %x\n", (void *)i, *temp & 0xff); } */ /*-done-copy args to user stack-----------*/ /* Warp to user mode. */ enter_new_process(argc /*argc*/, (userptr_t)argvPtr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv( userptr_t upname, userptr_t uargs ) { struct addrspace *as_new = NULL; struct addrspace *as_old = NULL; struct vnode *vn = NULL; vaddr_t entry_ptr; vaddr_t stack_ptr; int err; char kpname[MAX_PROG_NAME]; int nargs; int buflen; KASSERT( curthread != NULL ); KASSERT( curthread->td_proc != NULL ); (void)uargs; //lock the execv args lock_acquire( lk_exec ); //copy the old addrspace just in case. as_old = curthread->t_addrspace; //copyin the program name. err = copyinstr( upname, kpname, sizeof( kpname ), NULL ); if( err ) { lock_release( lk_exec ); return err; } //try to open the given executable. err = vfs_open( kpname, O_RDONLY, 0, &vn ); if( err ) { lock_release( lk_exec ); return err; } //copy the arguments into the kernel buffer. err = copy_args( uargs, &nargs, &buflen ); if( err ) { lock_release( lk_exec ); vfs_close( vn ); return err; } //create the new addrspace. as_new = as_create(); if( as_new == NULL ) { lock_release( lk_exec ); vfs_close( vn ); return ENOMEM; } //activate the new addrspace. as_activate( as_new ); //temporarily switch the addrspaces. curthread->t_addrspace = as_new; //load the elf executable. err = load_elf( vn, &entry_ptr ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //create a stack for the new addrspace. err = as_define_stack( as_new, &stack_ptr ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //adjust the stackptr to reflect the change stack_ptr -= buflen; err = adjust_kargbuf( nargs, stack_ptr ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //copy the arguments into the new user stack. err = copyout( kargbuf, (userptr_t)stack_ptr, buflen ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //reelase lk_exec lock_release( lk_exec ); //no need for it anymore. vfs_close( vn ); //we are good to go. as_destroy( as_old ); //off we go to userland. enter_new_process( nargs-1, (userptr_t)stack_ptr, stack_ptr, entry_ptr ); panic( "execv: we should not be here." ); return EINVAL; }
int sys_execv(userptr_t progname, userptr_t args){ /*This function implements the execv functionality*/ size_t get, offset; struct vnode *v; vaddr_t entrypoint, stackptr; userptr_t userdest; int i=0, append_zero, argc=0, result, part=0; char *buf_mem; int n=0; struct addrspace *old_addr = curthread->t_vmspace; char **usr_args = (char**)args; buf_mem = (void *) kmalloc(sizeof(void *)); result = copyin((const_userptr_t)args,buf_mem,4); if (result){ kfree(buf_mem); return result; } lock_acquire(execv_lock); kfree(buf_mem); while(usr_args[argc] != NULL){ argc++; } size_t len_string[argc]; userptr_t user_argv[argc]; char *args_buf = kmalloc(PAGE_SIZE*sizeof(char)); // Check user pointer buf_mem = (char *)kmalloc(1024*sizeof(char)); if (buf_mem == NULL){ result = ENOMEM; kfree(args_buf); } result = copyinstr((const_userptr_t)progname,buf_mem,1024,&get); if (result){ kfree(buf_mem); } //Implementation from runprogram from here /* Open the file. */ result = vfs_open((char *)progname, O_RDONLY, &v); if (result) { kfree(buf_mem); } // Keep old addrspace in case of failure struct addrspace *new_addr = as_create(); if (new_addr == NULL){ result = ENOMEM; vfs_close(v); } while (usr_args[i] != NULL){ result = copyinstr((const_userptr_t)usr_args[i], &args_buf[part], PAGE_SIZE, &len_string[i]); if (result){ as_destroy(new_addr); } part += len_string[i]; i++; } /* Swap addrspace and Activate it*/ curthread->t_vmspace = new_addr; as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } // Copy args to new addrspace offset = 0; for (i=argc-1; i>-1; i--){ part -= len_string[i]; // readjust inherited part index append_zero = (4 - (len_string[i]%4) ) % 4; // Word align offset += append_zero; offset += len_string[i]; user_argv[i] = (userptr_t)(stackptr - offset); result = copyoutstr((const char*)&args_buf[part], user_argv[i], len_string[i], &get); if (result){ curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } } // Copy pointers to argv userdest = user_argv[0] - 4 * (argc+1); stackptr = (vaddr_t)userdest; // Set stack pointer for (i=0; i<argc; i++){ result = copyout((const void *)&user_argv[i], userdest, 4); if (result) curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); userdest += 4; } // Wrap up kfree(args_buf); vfs_close(v); /* Warp to user mode. */ md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); lock_release(execv_lock); return EINVAL; }
int sys_execv(const char *program, char *args[]) { char **args_copy; struct vnode *v; int argc, result, index; vaddr_t stackptr, entrypoint; // get number of arguments for (argc=0; args[argc] != NULL; argc++); // save out copy of args before current address space is scrapped char *strtemp; args_copy = kmalloc(argc * sizeof(char *) + 1); for (index=0; index<argc; index++) { strtemp = kmalloc(sizeof(char)); strcpy(strtemp, args[index]); args_copy[index] = strtemp; } // do parameter checks if (program != args[0]) { //kprintf("Mismatch: program name %s does not match first argument %s.\n", program, args[0]); } assert(args[argc] == NULL); // open the program file result = vfs_open((char *)program, O_RDONLY, &v); if (result) { kprintf("open program file: %s\n", strerror(result)); return result; } // configure the user address space curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } as_activate(curthread->t_vmspace); // load the elf result = load_elf(v, &entrypoint); if (result) { kprintf("load elf: %s\n", strerror(result)); vfs_close(v); return result; } // close the program file since we're done with it vfs_close(v); // define the user stack result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { kprintf("define user stack: %s\n", strerror(result)); return result; } // put arguments onto user stack store_program_arguments(argc, args_copy, &stackptr); kfree(args_copy); // Warp to user mode md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); // md_usermode should not return (otherwise its an error) panic("md_usermode returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **argv, int argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } int i, bytes; vaddr_t argvaddr[argc+1]; for (i = 0; i < argc; i++) { bytes = strlen(argv[i]); bytes += 4 - bytes%4; //padding stackptr -= bytes; argvaddr[i] = stackptr; copyout(argv[i], (userptr_t)stackptr, bytes); kfree(argv[i]); } kfree(argv); argvaddr[argc] = 0; stackptr -= sizeof(vaddr_t)*(argc+1); copyout(argvaddr, (userptr_t) stackptr, 4*(argc+1)); /* Warp to user mode. */ enter_new_process(argc /*argc*/,(userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /** Initialize the file descriptors for console**/ if (curthread->t_fdtable[0] == NULL) { result = init_file_descriptor(); if (result ) { // file descriptors not initialized kprintf_n("init_file_descriptor failed"); return result; } } /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, NULL /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int execv(const char *prog_name, char **argv) { if( prog_name == NULL || argv == NULL ) return EFAULT; int argc = 0; size_t actual; char progname[__NAME_MAX]; int err = copyinstr((const_userptr_t) prog_name, progname, __NAME_MAX, &actual); if(err != 0){ return EFAULT; } /*if ( progname == (const char *)0x40000000 || progname == (const char *)0x80000000 || argv == (char **)0x40000000 || argv == (char **)0x80000000) return EFAULT; if( strcmp(progname,"") ) return EFAULT; if( strcmp((const char*)*argv,"") ) return EINVAL; if( strcmp(progname,"\0") ) return EINVAL; if( strcmp((const char*)*argv,"\0") ) return EINVAL; if( strlen(progname) == 0 ) return EINVAL; if( strlen((const char*)*argv) == 0 ) return EINVAL;*/ int i; for(i=0 ; argv[i] != NULL ; i++){ if(argv == (char **)0x40000000 || argv == (char **)0x80000000) return EFAULT; } argc = i; struct vnode *v; vaddr_t entrypoint, stackptr; int result; //Copy arguments into Temporary Kernel buffer char *ktemp[argc]; int argvlen[argc]; for( int m=0; m <argc; m++) { int len = strlen(argv[m])+1; argvlen[m] = len; int len_padding = len + (4 - (len % 4)); ktemp[m] = kmalloc(len_padding); size_t *p; err = copyinstr((const_userptr_t)argv[m], ktemp[m], len, p); } /* Open the file. */ result = vfs_open((char*)progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ //KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } // Load the arguments in user stack vaddr_t kargv[argc]; size_t len_from_top = 0; int arglen = 0, arglen_pad=0; if(argc > 0) { //kargv[argc]=0; for(int i=0 ; i < argc ; i++){ arglen = argvlen[i]; arglen_pad =arglen + (4- ((arglen)%4)); len_from_top = len_from_top + arglen_pad ; kargv[i] = stackptr - len_from_top; copyout(ktemp[i], (userptr_t) kargv[i], arglen_pad); kfree((void*)ktemp[i]); } stackptr = stackptr - len_from_top -(argc)*sizeof(vaddr_t); for(int i=0 ; i <argc ; i++){ copyout( &kargv[i], (userptr_t) stackptr, sizeof(vaddr_t)); stackptr = stackptr + sizeof(vaddr_t); } stackptr = stackptr - (argc)*sizeof(vaddr_t); /* Warp to user mode. */ enter_new_process( argc /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); } /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(const char *prog, char **userArgs) { struct vnode *v; vaddr_t entrypoint, stackptr; int res = 0; int length = 0; int index = 0; lock_acquire(allProcLock); char *progname; size_t size; progname = (char *) kmalloc(sizeof(char) * PATH_MAX); res = copyinstr((const_userptr_t) prog, progname, PATH_MAX, &size); char **args = (char **) kmalloc(sizeof(char **)); res = copyin((const_userptr_t)userArgs, args, sizeof(char **)); while (userArgs[index] != NULL) { args[index] = (char *) kmalloc(sizeof(char) * PATH_MAX); res = copyinstr((const_userptr_t) userArgs[index], args[index], PATH_MAX, &size); index++; } args[index] = NULL; index = 0; res = vfs_open(progname, O_RDONLY, 0, &v); struct addrspace *temp; temp = curproc->p_addrspace; if(curproc->p_addrspace != NULL){ as_destroy(curproc->p_addrspace); curproc->p_addrspace = NULL; } KASSERT(curproc->p_addrspace == NULL); if((curproc->p_addrspace = as_create()) == NULL){ kfree(progname); kfree(args); vfs_close(v); return ENOMEM; } as_activate(); res = load_elf(v, &entrypoint); vfs_close(v); res = as_define_stack(curproc->p_addrspace, &stackptr); while(args[index] != NULL) { char * arg; length = strlen(args[index]) + 1; int orignalLength = length; if(length % 4 != 0) { length = length + (4 - length % 4); } arg = kmalloc(sizeof(length)); arg = kstrdup(args[index]); for(int i = 0; i < length; i++){ if(i >= orignalLength){ arg[i] = '\0'; } else{ arg[i] = args[index][i]; } } stackptr -= length; res = copyout((const void *) arg, (userptr_t) stackptr, (size_t) length); kfree(arg); args[index] = (char *) stackptr; index++; } if(args[index] == NULL){ stackptr -= 4 * sizeof(char); } for(int i = (index - 1); i >= 0; i--) { stackptr = stackptr - sizeof(char*); res = copyout((const void *) (args + i), (userptr_t) stackptr, sizeof(char*)); } kfree(progname); kfree(args); lock_release(allProcLock); enter_new_process(index, (userptr_t) stackptr, stackptr, entrypoint); return EINVAL; }
runprogram(char *progname) #endif { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; //kprintf("bla0\n"); /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } //kprintf("bla1\n"); /* We should be a new process. */ KASSERT(curproc_getas() == NULL); //kprintf("bla2\n"); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } //kprintf("bla3\n"); /* Switch to it and activate it. */ curproc_setas(as); as_activate(); //kprintf("bla4\n"); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } //kprintf("bla5\n"); /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 //kprintf("bla6\n"); if(args == NULL){ return EFAULT; } // copy args to user size_t len = sizeof(char *) * (num + 1); char **copyargs = kmalloc(len); for(unsigned long int i = 0; i < num; i++){ len = strlen(args[i]) + 1; stackptr = stackptr - ROUNDUP(len, 8);//? limit or valid stackptr //new result = copyoutstr(args[i], (userptr_t)stackptr, len, NULL);//new if(result){ kfree(copyargs); return result; } copyargs[i] = (char *)stackptr; } copyargs[num] = NULL; // copy arr len = sizeof(char *) * (num + 1); stackptr = stackptr - ROUNDUP(len, 8); result = copyout(copyargs, (userptr_t)stackptr, len); kfree(copyargs); if(result){ return result; } userptr_t stackk = (userptr_t)stackptr; enter_new_process(num /*argc*/, stackk /*userspace addr of argv*/, stackptr, entrypoint); #else /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); #endif /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(const char* program, char** args, int* errno) { int ret; // simple error check // ************* if (program == NULL) { *errno = EFAULT; return -1; } // ************ // copies progname into kernel buffer // *************** char* fname = (char*)kmalloc(PATH_MAX); ret = copyinstr((userptr_t)program, fname, PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } // opens executable // *************** struct vnode* v; ret = vfs_open(fname, O_RDONLY, &v); if (ret != 0) { *errno = ret; return -1; } // ************** // gets argc // ************** int i = 0; while (args[i] != NULL) { i++; } int argc = i; // ************* // copies all arguments into kernel buffer // ***************** char** argv; argv= (char**)kmalloc(PATH_MAX); ret = copyin(args, argv, sizeof(userptr_t)); if (ret != 0) { *errno = EFAULT; return -1; } for(i = 0; i < argc; i++) { argv[i]=(char*)kmalloc(PATH_MAX); ret = copyinstr((userptr_t)args[i],argv[i], PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } } argv[argc] = NULL; // ******************* // error check // ************ if (curthread->t_vmspace != NULL) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; } // ************** // creates new address space and loads elf into it // ************** curthread->t_vmspace = as_create(); if (curthread->t_vmspace == NULL) { vfs_close(v); *errno = ENOMEM; return -1; } vaddr_t entrypoint,stackptr; as_activate(curthread->t_vmspace); ret = load_elf(v,&entrypoint); if (ret != 0){ vfs_close(v); *errno = ret; return -1; } vfs_close(v); ret = as_define_stack(curthread->t_vmspace,&stackptr); if (ret != 0) { *errno = ret; return -1; } // ******************** // copies arguments into userstack and increments stack ptr // ************** unsigned int pstack[argc]; for (i = argc-1; i >= 0; i--) { int len = strlen(argv[i]) + 1; stackptr -= len; stackptr -= stackptr%4; ret = copyoutstr(argv[i], (userptr_t)stackptr, PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } pstack[i] = stackptr; } pstack[argc] = (int)NULL; for (i = argc-1; i >= 0; i--) { stackptr -= 4; ret = copyout(&pstack[i], (userptr_t)stackptr, sizeof(pstack[i])); if (ret != 0) { *errno = EFAULT; return -1; } } // free unused memory for (i = 0; i < argc; i++) { kfree(argv[i]); } kfree(argv); kfree(fname); // ******************* // enters usermode, should not return // ******************* md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); // ****************** // if usermode returns, that is an error // ********** *errno = EINVAL; return -1; // ************ }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, int nargs) { struct vnode *v; vaddr_t entrypoint, stackptr, arguments[nargs+1], exactnewstackptr; int result, i; size_t len, offset = 0; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ struct addrspace * old_vmspace = curthread->t_vmspace; curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ curthread->t_vmspace = old_vmspace; vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ curthread->t_vmspace = old_vmspace; return result; } if(old_vmspace){ as_destroy(old_vmspace); } for (i = 0; i < nargs; i++) { len = strlen(args[i]) + 1; offset += len; arguments[i] = stackptr - offset; copyout((void *)args[i], (userptr_t) arguments[i], (size_t) len); } arguments[nargs] = 0; offset += sizeof(vaddr_t) * (nargs+1); exactnewstackptr = stackptr - offset; stackptr = exactnewstackptr - exactnewstackptr%4; copyout((void *) arguments, (userptr_t) stackptr, (size_t) sizeof(vaddr_t) * (nargs+1)); md_usermode(nargs, (userptr_t) stackptr, stackptr, entrypoint); panic("md_usermode returned\n"); return EINVAL; }
void run_process(void *ptr, unsigned long num) { (void)num; int result; vaddr_t entrypoint, stackptr; // extract and free passed-in context struct new_process_context *ctxt = (struct new_process_context *)ptr; struct process *proc = ctxt->proc; struct vnode *v = ctxt->executable; int nargs = ctxt->nargs; char **args = ctxt->args; kfree(ctxt); // attach process to thread curthread->t_proc = proc; proc->ps_thread = curthread; // Activate address space as_activate(proc->ps_addrspace); // Load the executable result = load_elf(v, &entrypoint); if (result) { vfs_close(v); kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Done with the file now vfs_close(v); // Define the user stack in the address space result = as_define_stack(proc->ps_addrspace, &stackptr); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Copy out arguments userptr_t uargv[nargs + 1]; for (int i = 0; i < nargs; i++) { int aligned_length = WORD_ALIGN(strlen(args[i]) + 1); stackptr -= aligned_length; uargv[i] = (userptr_t)stackptr; size_t arg_len; result = copyoutstr(args[i], uargv[i], strlen(args[i]) + 1, &arg_len); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } } uargv[nargs] =(userptr_t)NULL; // Copy out the argv array itself stackptr -= (nargs + 1) * sizeof(userptr_t); result = copyout(uargv, (userptr_t)stackptr, (nargs + 1) * sizeof(userptr_t)); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } enter_new_process(nargs, (userptr_t)stackptr, stackptr, entrypoint); // enter_new_process() does not return panic("enter_new_process returned\n"); }
int runprogram(char *progname, unsigned int argc, char**args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ #if OPT_A3 curthread->t_vmspace->elf_file = kstrdup(progname); #endif result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /*********************** stuff for A2 *******************/ char **args_u; /* user space arguments.(array of ptrs to string arguments.*/ /* string length of the arguments */ size_t argstrlen = getlen(argc, args); /* address space for the string arguments value. */ char *arg_str = (char *)stackptr - argstrlen; /* address space for the pointers to string arguments. */ args_u = (char **)arg_str - (argc+1)*sizeof(char**); /* adjust the address so that its divisable by 4 */ args_u = (int)args_u - (int)args_u%4; /* copy the arguments to the user address space */ int len; int i; for (i=0; i<argc; i++){ /* copy a single argument to the user address space */ copyoutstr(args[i], (userptr_t)arg_str, strlen(args[i])+1, &len); /* set the user argument to the current argument string pointer */ args_u[i] = arg_str; /* increment the argument pointer to the next argument */ arg_str += (strlen(args[i])+1)*sizeof(char); } /* set the n+1th argument to be NULL */ args_u[argc] = NULL; /* set the stackptr to the starting point of args_u and adjust the stack pointer */ stackptr = args_u - sizeof(char**) - ((int)args_u%8); /* Warp to user mode. */ md_usermode(argc, (userptr_t) args_u, stackptr, entrypoint); /*********************** end of A2 stuff *****************/ /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(const_userptr_t path, const_userptr_t argv) { int err; struct process *proc = curthread->t_proc; char *kpath = kmalloc(PATH_MAX); if (kpath == NULL) return ENOMEM; // copy in path size_t path_len; if ((err = copyinstr(path, kpath, PATH_MAX, &path_len))) { kfree(kpath); return err; } // give the process a new name char *old_name = proc->ps_name; proc->ps_name = kstrdup(kpath); if (proc->ps_name == NULL) { proc->ps_name = old_name; kfree(kpath); return ENOMEM; } // copy in args size_t argc; size_t total_len; char **kargv = kmalloc((ARGNUM_MAX + 1) * sizeof(char *)); err = copyinargs(argv, kargv, &argc, &total_len); if (err) { kfree(proc->ps_name); proc->ps_name = old_name; kfree(kpath); return err; } // Open the file. struct vnode *v; err = vfs_open(kpath, O_RDONLY, 0, &v); kfree(kpath); if (err) { free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // set up new address space struct addrspace *old_as = curthread->t_proc->ps_addrspace; struct addrspace *as = as_create(); if (as == NULL) { vfs_close(v); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return ENOMEM; } proc->ps_addrspace = as; // Activate the new address space as_activate(as); vaddr_t entrypoint; err = load_elf(v, &entrypoint); if (err) { proc->ps_addrspace = old_as; as_activate(old_as); as_destroy(as); vfs_close(v); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // close the file now, since we will not be returning // here from user mode. vfs_close(v); // set up user stack vaddr_t stackptr; err = as_define_stack(as, &stackptr); if (err) { proc->ps_addrspace = old_as; as_activate(old_as); as_destroy(as); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // copy arguments at base of stack stackptr -= total_len; stackptr -= (argc + 1) * sizeof(userptr_t); err = copyoutargs((userptr_t)stackptr, kargv, argc, total_len); if (err) { proc->ps_addrspace = old_as; as_activate(old_as); as_destroy(as); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // destroy old address space and free memory // that we will no longer need as_destroy(old_as); kfree(old_name); // Warp to user mode enter_new_process(argc, (userptr_t)stackptr, stackptr, entrypoint); // enter_new_process() does not return panic("enter_new_process returned\n"); return EINVAL; }
int sys___execv(char * p_name,char **ar ) { struct vnode *p_vnode; vaddr_t stackptr; vaddr_t entrypoint; int result; size_t copied_length; char *kname; if(p_name==NULL) return EFAULT; if(ar==NULL) return EFAULT; if(p_name == '\0') return ENOEXEC; kname = (char *) kmalloc(sizeof(p_name)); result = copyinstr((const_userptr_t)p_name,kname,NAME_MAX,&copied_length); if(copied_length == 1) { kfree(kname); return EINVAL; } if(result) { kfree(kname); return result; } char **karguments1 = kmalloc(100*sizeof(char*)); result = copyin((const_userptr_t) ar,karguments1,(100*sizeof(char*))); if(result) { kfree(karguments1); kfree(kname); return result; } else kfree(karguments1); char **arguments_kernel =(char **) kmalloc(sizeof(char**)); result = copyin((const_userptr_t) ar,arguments_kernel,(sizeof(char**))); if(result) { kfree(kname); kfree(arguments_kernel); return result; } char **karguments = (char **) kmalloc(sizeof(char **)); int counter=0; size_t actual_lenght1; while(!(ar[counter]==NULL)) { int string_length = strlen(ar[counter])+1; karguments[counter] = (char *) kmalloc(sizeof(char) * string_length); result = copyinstr((const_userptr_t) ar[counter],karguments[counter],string_length,&actual_lenght1); if(result) { kfree(kname); kfree(arguments_kernel); return result; } counter++; } karguments[counter] = NULL; result = vfs_open(kname, O_RDONLY, 0, &p_vnode); if (result) { return result; } as_destroy(curthread->t_addrspace); //Create a new address space. curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(p_vnode); return ENOMEM; } //Activate it. as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(p_vnode, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(p_vnode); return result; } /* Done with the file now. */ vfs_close(p_vnode); //Get the pointer to the stack starting result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } //Now copy the arguments int count =0; char **karray= kmalloc(sizeof(char**)); size_t final_stack=0; while(karguments[count] != NULL) { int string_length = strlen(karguments[count])+1; char *k_des= karguments[count]; int new_length = string_length; if((string_length) % 4 != 0) { while(new_length%4 !=0) { new_length++; } for(int i=string_length;i<=new_length;i++) { k_des[i]= '\0'; } } //Argument aligned by 4 size_t final_length= (size_t)new_length; if(count==0) { final_stack= stackptr- final_length; } else { final_stack= (size_t)karray[count-1]- final_length; } size_t actual_length1; result= copyoutstr(k_des, (userptr_t) (final_stack), final_length, &actual_length1); if(result) { return result; } karray[count]= (char*)(final_stack); count++; } //End of While karray[count]= (char*)NULL; int value= count+1; int arr_length = (value+1)*sizeof(char*); final_stack= (size_t)karray[count-1]- arr_length; result= copyout(karray, (userptr_t) (final_stack),arr_length); if(result) { return result; } /* Warp to user mode. */ enter_new_process(count /*argc*/, (userptr_t)(final_stack) /*userspace addr of argv*/, final_stack, entrypoint); return 0; }
int sys_execv(userptr_t progname_ptr, userptr_t args_ptr){ char* prog_name = kmalloc(PATH_MAX); size_t prog_name_len; if((char*)progname_ptr == NULL || (char**)args_ptr == NULL){ return EFAULT; } int argc = 0; char** args_ptrs = kmalloc(ARG_MAX); while(1){ char* arg = NULL; copyin(args_ptr+argc*sizeof(char*), &arg, sizeof(char*)); args_ptrs[argc] = arg; if(arg != NULL){ argc++; }else{ break; } } if(argc> 64){ return E2BIG; } int result_prog_name = copyinstr(progname_ptr,prog_name,PATH_MAX, &prog_name_len); if(result_prog_name != 0){ return result_prog_name; } char* argv = kmalloc(ARG_MAX); size_t * arg_offsets = kmalloc(argc * sizeof(size_t)); int offset = 0; for(int i = 0; i < argc; i++){ //char* arg = kmalloc(ARG_MAX); size_t arg_len; int result = copyinstr((userptr_t)args_ptrs[i], argv+offset, ARG_MAX - offset, &arg_len ); if(result != 0){ return result; } arg_offsets[i] = offset; offset += ROUNDUP(arg_len+1,8); //argv[i] = arg; } // prog_name (char*) AND argv (char*) struct addrspace *curproc_as = curproc_getas(); struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; vaddr_t cur_ptr; int result; /* Open the file. */ result = vfs_open(prog_name, O_RDONLY, 0, &v); if (result) { return result; } /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); // Have both argc and prog_name ready for runprogram cur_ptr = stackptr; cur_ptr -= offset; result = copyout(argv, (userptr_t)cur_ptr, offset); if(result != 0){ return result; } userptr_t * arg_offsets_up = kmalloc(sizeof(userptr_t) * (argc+1)); for(int i = 0; i < argc; i++){ userptr_t ptr = (userptr_t)cur_ptr + arg_offsets[i]; arg_offsets_up[i] = ptr; } arg_offsets_up[argc] = NULL; cur_ptr -= sizeof(userptr_t) * (argc+1); result = copyout(arg_offsets_up, (userptr_t)cur_ptr, sizeof(userptr_t) * (argc+1) ); if(result != 0){ return result; } as_destroy(curproc_as); kfree(arg_offsets); kfree(arg_offsets_up); kfree(argv); kfree(args_ptrs); kfree(prog_name); enter_new_process(argc /*argc*/, (userptr_t)cur_ptr /*userspace addr of argv*/, cur_ptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; //return 0; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char** args, size_t nargs) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; int argc = 0; while(args[argc] != NULL) { argc++; } /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 while(stackptr %8 != 0) stackptr--; vaddr_t argptr[argc + 1]; for (int i = argc - 1; i >= 0; i--) { stackptr -= strlen(args[i]) + 1; result = copyoutstr(args[i], (userptr_t) stackptr, strlen(args[i]) + 1, NULL); if(result) return result; argptr[i] = stackptr; } while(stackptr % 4 != 0) stackptr--; //int hack = (int) nargs; argptr[nargs] = 0; for (int i = argc; i >= 0; i--) { stackptr -= ROUNDUP(sizeof(vaddr_t), 4); result = copyout(&argptr[i], (userptr_t) stackptr, sizeof(vaddr_t)); if(result) return result; } #endif /* Warp to user mode. */ enter_new_process(nargs /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
runprogram(char *progname) #endif { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 // How much space do we need for args in stack? // We need space for each pointer (4argc) // We need space for each character, including NULL termination, plus // padding to make multiples of 4 int stringSpace = 0; for (unsigned long i = 0; i < argc; i++) { stringSpace += strlen(argv[i]) + 1; } // Align stack pointer to an 8-byte alignment while ((stackptr - (4*argc) - stringSpace) % 8 != 0) { stackptr--; } // Use a vaddr array to track the addresses the strings end up in // One bigger than argc to also have the pointer to the final NULL // value vaddr_t stringAddr[argc+1]; // Copy argument strings onto stack // Array must end with NULL pointer, so do that first stackptr -= 4; copyout((void *)NULL, (userptr_t)stackptr, (size_t)4); stringAddr[argc] = stackptr; for (int i = argc-1; i >= 0; i--) { stackptr -= strlen(argv[i]) + 1; while (stackptr % 4 != 0) stackptr--; copyoutstr(argv[i], (userptr_t)stackptr, (size_t)strlen(argv[i]), NULL); stringAddr[i] = stackptr; } // Now use the stored addresses of the string to add the appropriate // pointers to the stack for (int i = argc; i >= 0; i--) { stackptr -= sizeof(vaddr_t); copyout(&stringAddr[i], (userptr_t)stackptr, sizeof(vaddr_t)); } /* Warp to user mode. */ enter_new_process(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); #else /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); #endif /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int runprogram(char *progname) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { // p_addrspace will go away when curproc is destroyed return result; } struct vnode* v1; struct vnode* v2; struct vnode* v3; const char* name = "con:"; char *con_name = kstrdup(name); char *con_name2 = kstrdup(name); char *con_name3 = kstrdup(name); /*char con_name[5]; char con_name2[5]; char con_name3[5]; strcpy(con_name,name); strcpy(con_name2,name); strcpy(con_name3,name); */ result = vfs_open(con_name, O_RDONLY, 0664, &v1); if(result) { return result; } result = vfs_open(con_name2, O_WRONLY, 0664, &v2); if(result) { return result; } result = vfs_open(con_name3, O_WRONLY, 0664, &v3); if(result) { return result; } kfree(con_name); kfree(con_name2); kfree(con_name3); struct file_handle* fh1 = file_handle_create(); fh1->file = v1; fh1->openflags = O_RDONLY; fh1->ref_count = 1; strcpy(fh1->file_name,"con:"); curproc->t_file_table[0] = fh1; struct file_handle* fh2 = file_handle_create(); fh2->file = v2; fh2->openflags = O_WRONLY; fh2->ref_count = 1; strcpy(fh2->file_name, "con:"); curproc->t_file_table[1] = fh2; struct file_handle* fh3 = file_handle_create(); fh3->file = v3; fh3->openflags = O_WRONLY; fh3->ref_count = 1; strcpy(fh3->file_name, "con:"); curproc->t_file_table[2] = fh3; /* Warp to user mode. */ //kprintf("[run program] releasing semaphore \n"); enter_new_process(0 /*argc*/, 0 /*userspace addr of argv*/, NULL /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, int argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; // Variables for argument passing int i, pad; size_t offset, get; userptr_t userdest; size_t got[argc]; userptr_t user_argv[argc]; // Count length of each arg i = 0; for (i=0; i<argc; i++){ got[i] = strlen(args[i]) + 1; // Need +1 to account for /0 } /* We enforce that the kernel is only allowed to start ONE user process * directly through runprogram with PID_MIN as its pid. Thereafter any * new user process needs to be forked from existing ones. */ KASSERT(process_table[PID_MIN] == NULL); curthread->pid = PID_MIN; stdio_init(); /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } // Copy args to new addrspace offset = 0; for (i=argc-1; i>-1; i--){ pad = (4 - (got[i]%4) ) % 4; // Word align offset += pad; offset += got[i]; user_argv[i] = (userptr_t)(stackptr - offset); result = copyoutstr((const char*)args[i], user_argv[i], got[i], &get); if (result){ return result; } } // Copy pointers to argv userdest = user_argv[0] - 4 * (argc+1); stackptr = (vaddr_t)userdest; // Set stack pointer for (i=0; i<argc; i++){ result = copyout((const void *)&user_argv[i], userdest, 4); if (result){ return result; } userdest += 4; } /* Warp to user mode. */ enter_new_process(argc, (userptr_t)stackptr, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(userptr_t progname, userptr_t uargs_ptr){ // char* name int err; char* program = (char*)kmalloc(20); size_t prog_len; err = copyinstr((userptr_t)progname, program, 1024, &prog_len); if(err){ return err; } if(prog_len == 1) return EINVAL; char** uargs = (char**)kmalloc(100); // this could be causing problems maybe err = copyin((userptr_t)uargs_ptr, uargs, 100); if(err){ return err; } // Get number of arguments size_t nargs = 0; while(uargs[nargs] != NULL){ nargs++; if(nargs >= MAX_ARGS){ return E2BIG; } } int wordlen; int argLengths[nargs]; // Store the length of each argument, including the 1 null terminator // but NOT including the padding for alignment. for(size_t i = 0; i < nargs; i++){ char arg[100]; err = copyin((userptr_t)uargs[i],arg,100); if(err) return err; wordlen = strlen(uargs[i]) + 1; // Add 1 to account for Null terminator! // pad = 4 - (wordlen % 4); // Don't worry about padding yet // if(pad == 4){ pad = 0; } // // totalLength += wordlen; // Don't need this... argLengths[i] = wordlen; } char** args = kmalloc(sizeof(char*) * nargs); // Still need to populate args with each individual argument if(args == NULL){ panic("kmalloc failed :'("); } size_t arg_num = 0; while(arg_num < nargs){ args[arg_num] = kmalloc(argLengths[arg_num] * sizeof(char)); err = copyin((userptr_t)uargs[arg_num], args[arg_num], argLengths[arg_num]); if(err) return err; arg_num++; } int result; struct vnode *v; vaddr_t entrypoint, stackptr; /* Open the file. */ result = vfs_open(program, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ // KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } // This is where runprogram stuff starts! // vaddr_t entrypoint, stackptr; int individualArgSize[nargs]; size_t totalLength = 0; size_t pad; for(size_t i = 0; i < nargs; i++){ wordlen = strlen(args[i]) + 1; // Add 1 to account for Null terminator! pad = 4 - (wordlen % 4); if(pad == 4){ pad = 0; } totalLength += wordlen + pad; } char* words_contiguous = kmalloc(sizeof(char) * totalLength); int j; for(size_t i = 0; i < nargs; i++){ j = 0; while(args[i][j] != '\0'){ *words_contiguous = args[i][j]; words_contiguous++; j++; } // At this point, j is the length of the word without any null bytes. *words_contiguous = '\0'; words_contiguous++; // Now calculate the number of padding null bytes for alignment. pad = 4 - ((j + 1) % 4); if(pad == 4){ pad = 0; } // Add the null bytes for(size_t p = 0; p < pad; p++){ *words_contiguous = '\0'; words_contiguous++; } individualArgSize[i] = j + 1 + pad; //Just getting the pointer size... } // Reset pointer back to start of C-string. words_contiguous = words_contiguous - totalLength; size_t totalStackSize; totalStackSize = totalLength + ((nargs + 1) * sizeof(char*)); // Adjust to copyout the words (totalLength) stackptr = stackptr - totalLength; copyout(words_contiguous, (userptr_t)stackptr, totalLength); // Adjust to bottom of where we'll modify stack. // stackptr = stackptr - (totalStackSize - totalLength); // KASSERT((totalStackSize - totalLength) == sizeof(args)); args[0] = (char*)stackptr; stackptr = stackptr + individualArgSize[0]; for(size_t argNumber = 1; argNumber < nargs; argNumber++){ args[argNumber] = (char*)stackptr; stackptr = stackptr + individualArgSize[argNumber]; } // stackptr should be at 80000000 right now. // Set stackptr back to bottom of stack; stackptr = stackptr - totalStackSize; // Copy args (pointers to stack addresses) onto the stack, below the words. copyout(args, (userptr_t)stackptr, (totalStackSize - totalLength)); // Create Null pointer. args[0] = NULL; // Copy null pointer to stack copyout(args, (userptr_t)(stackptr+((totalStackSize - totalLength) - 4)), 4); // TODO: Free words contiguous at some point (memory leak) kfree(words_contiguous); kfree(args); kfree(program); //kfree(uargs); /* Warp to user mode. */ //TODO: Change enter_new_process(nargs /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); (void)nargs; /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, unsigned long nargs) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /*Initialize Console*/ char *consolein; char *consoleout; char *consoleerr; consolein = kstrdup("con:"); consoleout = kstrdup("con:"); consoleerr = kstrdup("con:"); curthread->t_fdtable[0] = (struct fdesc*) kmalloc(sizeof(struct fdesc)); if (vfs_open(consolein, O_RDONLY, 0664, &(curthread->t_fdtable[0]->vn))) { return EINVAL; } curthread->t_fdtable[0]->name = consolein; curthread->t_fdtable[0]->flag = O_RDONLY; curthread->t_fdtable[0]->ref_count = 1; curthread->t_fdtable[0]->filelock = lock_create("STDIN"); kfree(consolein); curthread->t_fdtable[1] = (struct fdesc*) kmalloc(sizeof(struct fdesc)); if (vfs_open(consoleout, O_WRONLY, 0664, &(curthread->t_fdtable[1]->vn))) { return EINVAL; } curthread->t_fdtable[1]->name = consoleout; curthread->t_fdtable[1]->flag = O_WRONLY; curthread->t_fdtable[1]->ref_count = 1; curthread->t_fdtable[1]->filelock = lock_create("STDOUT"); kfree(consoleout); curthread->t_fdtable[2] = (struct fdesc*) kmalloc(sizeof(struct fdesc)); if (vfs_open(consoleerr, O_WRONLY, 0664, &(curthread->t_fdtable[2]->vn))) { return EINVAL; } curthread->t_fdtable[2]->name = consoleerr; curthread->t_fdtable[2]->flag = O_WRONLY; curthread->t_fdtable[2]->ref_count = 1; curthread->t_fdtable[2]->filelock = lock_create("STDERR"); kfree(consoleerr); /*Console Initialized*/ /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace == NULL ) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } int argc = (signed) nargs; int err; char** argv; //kmalloc argv with size of char* times nargs+1 argv = kmalloc((nargs + 1) * sizeof(userptr_t)); size_t len; for (int i = 0; i < argc; i++) { len = strlen(args[i]) + 1; len = (len + 4 - 1) & ~(size_t) (4 - 1); stackptr -= len; if ((err = copyout(args[i], (userptr_t) stackptr, len)) != 0) { kprintf("error copyout"); } argv[i] = (char*) stackptr; } argv[nargs] = NULL; stackptr -= (nargs + 1) * sizeof(userptr_t); if ((err = copyout(argv, (userptr_t) stackptr, (nargs + 1) * sizeof(char*)))) { kprintf("error copying"); } /* Warp to user mode. */ enter_new_process(argc, (userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(char* program, char** args) { int result; char name[strlen(program) + 1]; result = copyin((userptr_t) program, name, (strlen(program) + 1) * sizeof(char)); //kprintf("%s", name); int len_arg = 0; while(args[len_arg] != NULL) { len_arg++; } int length_every_arg[len_arg]; for(int i = 0; i < len_arg; i++) { length_every_arg[i] = strlen(args[i]); } char* kern_args[len_arg]; for(int i = 0; i < len_arg; i++) { kern_args[i] = kmalloc(sizeof(char) * length_every_arg[i] + 1); copyin((const_userptr_t)args[i], kern_args[i], (length_every_arg[i] + 1) * sizeof(char)); } /* for(int i = 0; i < len_arg; i++) { kprintf("{ _%d__%p__%p_",strlen(kern_args[i]), kern_args[i],args[i]); kprintf("%s", kern_args[i]); kprintf("}\n"); } */ ///////////////////////////////////////////////////// // this is "copied" from runprogram struct addrspace* old_as; struct vnode* v; vaddr_t entrypoint, stackptr; result = vfs_open(program, O_RDONLY, 0, &v); if(result) { return result; } as_deactivate(); old_as = curproc_setas(NULL); as_destroy(old_as); struct addrspace* new_as = as_create(); if(new_as == NULL) { vfs_close(v); return ENOMEM; } curproc_setas(new_as); as_activate(); result = load_elf(v, &entrypoint); if(result) { vfs_close(v); return result; } vfs_close(v); result = as_define_stack(new_as, &stackptr); if(result) { return result; } ////////////////////////////////////////////////////////// // kern_args // the addr of stackptr is 0x8000 0000 vaddr_t argv = stackptr; for(int i = 0; i < len_arg + 1; i++) { argv = argv - 4; } vaddr_t start = argv; vaddr_t temp = argv; copyout(NULL, (userptr_t)(stackptr - 4), 4); //starts from 1, because argv[0] is reserved for the program name for(int i = 0; i < len_arg; i++) { //question? why do I have to add 2 int m = sizeof(char) * (strlen(kern_args[i]) + 1); // kprintf("the value of m -> %d\n", m); argv = argv - m; copyout(kern_args[i], (userptr_t)argv, m); // kprintf("***(%d)%s(%p)\n***", m, (char* )argv, (void *) argv); copyout(&argv, (userptr_t)temp, sizeof(char* )); temp = temp + 4; } for(int i = 0; i < len_arg; i++) { kfree(kern_args[i]); } while(argv % 8 != 0) {argv--;} enter_new_process(len_arg, (userptr_t)start, (vaddr_t) argv, entrypoint); // enter_new_process(0, NULL, stackptr, entrypoint); panic("enter_new_process returned"); return EINVAL; }