예제 #1
0
파일: runprogram.c 프로젝트: mellwa/os
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;
}
예제 #2
0
파일: runprogram.c 프로젝트: JayP16/OS161
/*
 * 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;
}
예제 #3
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)
{
	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;
}
예제 #5
0
파일: thread.c 프로젝트: MattMarji/os161
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);
	

}
예제 #6
0
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;
}
예제 #7
0
파일: runprogram.c 프로젝트: gapry/os161
/*
 * 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;
}
예제 #8
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, 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;
}
예제 #9
0
파일: execv.c 프로젝트: script3r/os161
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;
}
예제 #10
0
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;
}
예제 #12
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 **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;
}
예제 #13
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)
{
	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;
}
예제 #14
0
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;
}
예제 #15
0
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;

}
예제 #16
0
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;
}
예제 #17
0
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;
	// ************
}
예제 #18
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, 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;
}
예제 #19
0
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");
}
예제 #20
0
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;
}
예제 #21
0
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;
}
예제 #22
0
파일: psyscall.c 프로젝트: coderpm/OS161
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;
}
예제 #23
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;
}
예제 #24
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;
}
예제 #25
0
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;
}
예제 #26
0
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;
}
예제 #27
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, 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;
}
예제 #28
0
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;
}
예제 #29
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, 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;
}
예제 #30
0
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;
}