Index: trunk/kernel/syscalls/sys_exec.c
===================================================================
--- trunk/kernel/syscalls/sys_exec.c	(revision 14)
+++ trunk/kernel/syscalls/sys_exec.c	(revision 23)
@@ -1,7 +1,6 @@
 /*
- * sys_exec.c - Kernel function implementing the "exec" syscall
+ * sys_exec.c - Kernel function implementing the "exec" system call.
  * 
- * Authors    Mohamed Lamine Karaoui (2015)
- *            Alain Greiner          (2016)
+ * Authors   Alain Greiner (2016,2017)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -25,4 +24,5 @@
 #include <kernel_config.h>
 #include <hal_types.h>
+#include <hal_uspace.h>
 #include <errno.h>
 #include <printk.h>
@@ -51,10 +51,7 @@
 
     // get string length
-	hal_strlen_from_uspace( pathname , &length );
-	if( length > 255 ) 
-    {
-        printk(ERROR, "%s: elf file pathname larger than 255 bytes\n", __FUNCTION__ );
-        return EINVAL;
-    }
+	length = hal_strlen_from_uspace( pathname );
+
+	if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) return EINVAL;
 
     // copy string to exec_info
@@ -75,5 +72,5 @@
 // The max number of strings is 1024 (for both args and envs). The numbers of pages 
 // to store the (args) and (envs) strings are configuration parameters.
-////////////////////////////////////////////////i////////////////////////////////////// 
+/////////////////////////////////////////////////////////////////////////////////////// 
 // @ exec_info : pointer on the exec_info structure.
 // @ is_args   : true if called for (args) / false if called for (envs).
@@ -88,15 +85,14 @@
     uint32_t     found_null;  // NULL pointer found in array of pointers
     uint32_t     length;      // string length
-    uint32_t     strings;     // actual number of strings
     kmem_req_t   req;         // kmem request
     page_t     * page;        // page descriptor
     uint32_t     order;       // ln2( number of pages to store strings )
-    char      ** k_pointers;  // base of kernel buffer containing array of pointers
-    char       * buf_ptr;     // pointer on first empty slot in kernel strings buffer
-    char       * buf_base;    // base address of the kernel strings buffer
+    char      ** k_pointers;  // base of kernel array of pointers
+    char       * k_buf_ptr;   // pointer on first empty slot in kernel strings buffer
+    char       * k_buf_base;  // base address of the kernel strings buffer
 
     // compute ln2( number of pages for kernel strings buffer )
-    if( is_args ) order = CONFIG_PROCESS_ARGS_ORDER;
-    else          order = CONFIG_PROCESS_ENVS_ORDER;
+    if( is_args ) order = bits_log2( CONFIG_VMM_ARGS_SIZE );
+    else          order = bits_log2( CONFIG_VMM_ENVS_SIZE );
 
 	req.type   = KMEM_PAGE;
@@ -106,9 +102,7 @@
     req.type   = 0;
     page       = kmem_alloc( &req );
-    if( page == NULL )
-    {
-        printk("ERROR in %s : cannot allocate memory for pointers\n", __FUNCTION__ );
-        return ENOMEM;
-    }
+
+    if( page == NULL ) return ENOMEM;
+
     k_pointers = ppm_page2base( page );
     
@@ -116,10 +110,8 @@
     req.type   = order;
     page       = kmem_alloc( &req );
-    if( page == NULL )
-    {
-        printk("ERROR in %s : cannot allocate memory for strings\n", __FUNCTION__ );
-        return ENOMEM;
-    }
-    buf_base    = ppm_page2base( page );
+
+    if( page == NULL ) return ENOMEM;
+
+    k_buf_base = ppm_page2base( page );
     
     // copy the array of pointers to kernel buffer 
@@ -128,7 +120,7 @@
                           CONFIG_PPM_PAGE_SIZE );
 
-    // scan local copy of array of pointers to copy the strings
+    // scan kernel array of pointers to copy the strings
     found_null = 0;
-    buf_ptr    = buf_base;
+    k_buf_ptr  = k_buf_base;
     for( index = 0 ; index < 1024 ; index++ )
     {
@@ -140,16 +132,16 @@
 
         // compute string length
-	    hal_strlen_from_uspace( k_pointers[index] , &length );
+	    length = hal_strlen_from_uspace( k_pointers[index] );
  
         // copy the user string to kernel buffer
-        hal_copy_from_uspace( k_strings,
-                              k_pointers[index];
+        hal_copy_from_uspace( k_buf_ptr,
+                              k_pointers[index],
                               length );
 
         // update k_pointer[index] entry
-        k_pointers[index] = buf_ptr;
+        k_pointers[index] = k_buf_ptr;
 
         // increment pointer on kernel strings buffer
-        buf_ptr += (length + 1);
+        k_buf_ptr += (length + 1);
     }
 
@@ -158,5 +150,5 @@
     {
         exec_info->args_pointers  =  k_pointers;
-        exec_info->args_buf_base  =  buf_base;
+        exec_info->args_buf_base  =  k_buf_base;
         exec_info->args_nr        =  index;
     }
@@ -164,11 +156,10 @@
     {
         exec_info->envs_pointers  =  k_pointers;
-        exec_info->envs_buf_base  =  buf_base;
-        exec_info->envs_buf_free  =  buf_ptr;
+        exec_info->envs_buf_base  =  k_buf_base;
+        exec_info->envs_buf_free  =  k_buf_ptr;
         exec_info->envs_nr        =  index;
     }
     else 
     {
-        printk("ERROR in %s : number of strings larger than 1024\n", __FUNCTION__ );
         return EINVAL;
     }
@@ -177,10 +168,4 @@
 } // end process_exec_get_strings()
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// This function is executed in a "client" cluster by a process whose PID can belong
-// to another "server" cluster (defined by the MSB bits of the calling process PID).
-// A new process descriptor, and the associated main thread descriptor must be created
-// in the "server" cluster, using directly the process_make_exec() function if local,
-// or the rpc_process_exec_client() function if server is remote.
 /////////////////////////////////////////////////////////////////////////////////////////
 // Implementation note:
@@ -189,21 +174,45 @@
 // It calls the static process_exec_get_path() and process_exec_get_strings() functions
 // to copy the .elf pathname, the main() arguments and the environment variables from
-// user buffers to the exec_info_t, and calls the static process_make_exec() function.
+// user buffers to the exec_info_t structure, and call the process_make_exec() function.
 /////////////////////////////////////////////////////////////////////////////////////////
 int sys_exec( char  * filename,     // .elf file pathname
-              char ** argv,         // process arguments
-              char ** envp )        // environment variables
+              char ** args,         // process arguments
+              char ** envs )        // environment variables
 {
     exec_info_t  exec_info;         // structure to pass to process_make_exec()
-    thread_t   * thread;            // pointer on thread created in server cluster
-	error_t      error   = 0;
-	process_t  * process = CURRENT_PROCESS;
-
-    // check arguments
-	if((filename == NULL) || (argv == NULL) || (envp == NULL)) 
-    {
-        printk("\n[ERROR] in %s : missing arguments / file = %x / argv = %x / envp = %x\n",
-               __FUNCTION__ , filename , argv , envp );
-        return EINVAL;
+	error_t      error;
+    paddr_t      paddr;
+
+    thread_t   * this    = CURRENT_THREAD;
+	process_t  * process = this->process;
+
+    // check argument fileme
+    error = vmm_v2p_translate( false , filename , &paddr );
+
+	if( error )
+    {
+        printk("\n[ERROR] in %s : filename unmapped\n", __FUNCTION__ );
+        this->errno = EINVAL;
+        return -1;
+    }
+
+    // check argument fileme
+    error = vmm_v2p_translate( false , args , &paddr );
+
+	if( error )
+    {
+        printk("\n[ERROR] in %s : args unmapped\n", __FUNCTION__ );
+        this->errno = EINVAL;
+        return -1;
+    }
+
+    // check argument fileme
+    error = vmm_v2p_translate( false , envs , &paddr );
+
+	if( error )
+    {
+        printk("\n[ERROR] in %s : envs unmapped\n", __FUNCTION__ );
+        this->errno = EINVAL;
+        return -1;
     }
 
@@ -218,67 +227,65 @@
                  cxy_client, cxy_server, hal_time_stamp());
 
-    // Change process's state to prevent any concurent access TODO ??? [AG]
-
     // initialize exec_info structure 
-    exec_info->pid      = process->pid;
-    exec_info->ppid     = process->ppid;
-    exec_info->fd_array = &process->fd_array;
-    exec_info->vfs_root = &process->vfs_root;
-    exec_info->vfs_cwd  = &process->vfs_cwd;
-    exec_info->vfs_bin  = &process->vfs_bin;
+    exec_info.pid         = process->pid;
+    exec_info.ppid        = process->ppid;
+    exec_info.fd_array_xp = XPTR( local_cxy , &process->fd_array );
+    exec_info.vfs_root_xp = process->vfs_root_xp;
+    exec_info.vfs_cwd_xp  = process->vfs_cwd_xp;
+    exec_info.vfs_bin_xp  = process->vfs_bin_xp;
 
 	// check pathname and store it in exec_info structure
 	error = process_exec_get_path( &exec_info , filename );
-	if ( error ) return EINVAL;
-
-	// check and store argv in exec_info structure
-	error = process_exec_get_strings( &exec_info , true , argv );
-	if( error )  return EINVAL;
+
+	if ( error )
+    {
+        printk("\n[ERROR] in %s : elf pathname too long\n", __FUNCTION__ );
+        this->errno = error;
+        return -1;
+    }
+
+	// check and store args in exec_info structure
+	error = process_exec_get_strings( &exec_info , true , args );
+
+	if( error )  
+    {
+        printk("\n[ERROR] in %s : cannot access args\n", __FUNCTION__ );
+        this->errno = error;
+        return -1;
+    }
 	
-	// check and store envp in exec_info structure
-	error = process_exec_get_strings( &exec_info , false , envp );
-	if( error )  return EINVAL;
+	// check and store envs in exec_info structure
+	error = process_exec_get_strings( &exec_info , false , envs );
+
+	if( error )
+    {
+        printk("\n[ERROR] in %s : cannot access envs\n", __FUNCTION__ );
+        this->errno = error;
+        return -1;
+    }
 	
-    if( is_local )  ////////////// local exec ////////////////////////// 
-    {
-        exec_dmsg("\n[INFO] %s starts local exec for process %x at cycle %d\n",
-                  __FUNCTION__, process->pid, hal_time_stamp());
-
-        // call directly the local process_make_exec() function
-        error = process_make_exec( &exec_info , &thread );
-        if error
-        {
-            printk("\n[ERROR] in %s : failed in local exec for process %x\n",
-                   __FUNCTION__ , process->pid );
-            return EINVAL;
-        }
-
-        exec_dmsg("\n[INFO] %s completes local exec for process %x at cycle %d\n",
-                  __FUNCTION__, process->pid , hal_time_stamp() );
-    }
-    else             ///////////// remote exec /////////////////////////
-    {
-        exec_dmsg("\n[INFO] %s starts remote exec for process %x at cycle %d\n",
-                  __FUNCTION__, process->pid, hal_time_stamp() );
-
-        // call the rpc_process_exec_client() function    
-        rpc_process_exec_client( cxy_server , &exec_info , &thread , &error );
-
-        if( error )
-        {
-            printk("\n[ERROR] in %s : failed in remote exec for process %x\n",
-                   __FUNCTION__ , process->pid );
-            return EINVAL;
-        }
-
-        exec_dmsg("\n[INFO] %s completes remote exec for process %x at cycle %d\n",
-                  __FUNCTION__, process->pid , hal_time_stamp() );
-    }
-
-    // If no error, delete the current thread an process descriptors.
+    exec_dmsg("\n[INFO] %s starts exec for process %x at cycle %d\n",
+              __FUNCTION__, process->pid, hal_time_stamp() );
+
+    if( is_local )  error = process_make_exec( &exec_info );
+    else            rpc_process_exec_client( cxy_server , &exec_info , &error );
+
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot create new process %x\n",
+               __FUNCTION__ , process->pid );
+        this->errno = error;
+        return -1;
+    }
+
+    exec_dmsg("\n[INFO] %s completes exec for process %x at cycle %d\n",
+              __FUNCTION__, process->pid , hal_time_stamp() );
+
+    // delete the calling thread an process
     thread_kill( CURRENT_THREAD );
-    process_kill( CURRENT_PROCESS );
+    process_kill( CURRENT_THREAD->process );
 
     return 0;
+
 } // end sys_exec()
 
