Index: trunk/user/ksh/ksh.c
===================================================================
--- trunk/user/ksh/ksh.c	(revision 574)
+++ trunk/user/ksh/ksh.c	(revision 588)
@@ -45,4 +45,5 @@
 #include <almosmkh.h>
 #include <semaphore.h>
+#include <hal_macros.h>
 
 #define CMD_MAX_SIZE   (256)    // max number of characters in one command
@@ -319,5 +320,5 @@
 	    cxy = atoi(argv[2]);
 
-        if( display_cluster_processes( cxy ) )
+        if( display_cluster_processes( cxy , 0 ) )
         {
             printf("  error: illegal argument cxy = %x\n", cxy );
@@ -465,8 +466,10 @@
 	char               * pathname;           // path to .elf file
     unsigned int         background;         // background execution if non zero
-
-	if( (argc < 2) || (argc > 3) )  
-    {
-		printf("  usage: %s pathname [&] / argc = %d\n", argv[0], argc );  // @@@
+    unsigned int         placement;          // placement specified if non zero
+    unsigned int         cxy;                // target cluster if placement specified
+
+	if( (argc < 2) || (argc > 4) )  
+    {
+		printf("  usage: %s pathname [cxy] [&]\n", argv[0] );
 		return;
 	}
@@ -474,6 +477,31 @@
 	pathname = argv[1];
 
-    if( argc == 3 ) background = (argv[2][0] == '&');
-    else            background = 0;
+    if( argc == 2 )
+    {
+        background = 0;
+        placement  = 0;
+        cxy        = 0;
+    }
+    else if( argc == 3 )
+    {
+        if( (argv[2][0] == '&') && (argv[2][1] == 0) )
+        {
+            background = 1;
+            placement  = 0;
+            cxy        = 0;
+        }
+        else 
+        {
+            background = 0;
+            placement  = 1;
+            cxy        = atoi( argv[2] );
+        }
+    }
+    else  // argc == 4
+    { 
+        background = ( (argv[3][0] == '&') && (argv[3][1] == 0) );
+        placement  = 1;
+        cxy        = atoi( argv[2] );
+    }
 
     // get KSH process PID
@@ -483,7 +511,10 @@
 long long unsigned cycle;
 get_cycle( &cycle );
-printf("\n@@@ %s : KSH PID %x before fork / path %s / background %d / cycle %d\n",
-__FUNCTION__, ksh_pid, argv[1], background, (int)cycle );
+printf("\n[KSH] %s : ksh_pid %x / path %s / bg %d / place %d (%x) / cycle %d\n",
+__FUNCTION__, ksh_pid, argv[1], background, placement, cxy, (int)cycle );
 #endif
+
+    // set target cluster if required
+    if( placement ) place_fork( cxy );
 
     // KSH process fork CHILD process
@@ -500,5 +531,5 @@
 #if CMD_LOAD_DEBUG
 get_cycle( &cycle );
-printf("\n@@@ %s : CHILD_PID %x after fork, before exec / cycle %d\n",
+printf("\n[KSH] %s : child_pid %x after fork, before exec / cycle %d\n",
 __FUNCTION__ , getpid(), (int)cycle );
 #endif
@@ -509,5 +540,5 @@
 #if CMD_LOAD_DEBUG
 get_cycle( &cycle );
-printf("\n@@@ %s : CHILD_PID %x after exec / ret_exec %d / cycle %d\n",
+printf("\n[KSH] %s : child_pid %x after exec / ret_exec %d / cycle %d\n",
 __FUNCTION__ , getpid(), ret_exec, (int)cycle );
 #endif
@@ -525,5 +556,5 @@
 #if CMD_LOAD_DEBUG
 get_cycle( &cycle );
-printf("\n@@@ %s : KSH_PID %x after fork / ret_fork %x / cycle %d\n",
+printf("\n[KSH] %s : ksh_pid %x after fork / ret_fork %x / cycle %d\n",
 __FUNCTION__, getpid(), ret_fork, (int)cycle );
 #endif
@@ -636,4 +667,37 @@
 
 }  // end cmd_mv
+
+
+////////////////////////////////////////////
+static void cmd_ps( int argc , char **argv )
+{
+    unsigned int x_size;
+    unsigned int y_size;
+    unsigned int ncores;
+    unsigned int x;
+    unsigned int y;
+
+	if (argc != 1)
+    {
+		printf("  usage: %s\n", argv[0]);
+		return;
+	}
+
+    // get platform config
+    get_config( &x_size , &y_size , &ncores );
+
+    // scan all clusers
+    for( x = 0 ; x < x_size ; x++ )
+    {
+        for( y = 0 ; y < y_size ; y++ )
+        {
+            display_cluster_processes( HAL_CXY_FROM_XY(x,y), 1 );  // only owned processes
+        }
+    }
+
+    // release semaphore to get next command
+    sem_post( &semaphore );
+
+}  // end cmd_ps()
 
 /////////////////////////////////////////////
@@ -758,4 +822,5 @@
 	{ "mv",      "move a file in file system",                      cmd_mv      },
 	{ "pwd",     "print current working directory",                 cmd_pwd     },
+	{ "ps",      "display all processes",                           cmd_ps      },
 	{ "rm",      "remove a file from file system",                  cmd_rm      },
 	{ "rmdir",   "remove a directory from file system",             cmd_rmdir   },
@@ -830,20 +895,19 @@
 	unsigned int   state;                   // escape sequence state
 
-/* This can be used to simplify debug, as it avoids interactive mode
-
-for( i=1 ; 1 ; i++ )
-{
-    if( sem_wait( &semaphore ) )
-    {
-        printf("\n[ksh error] cannot found semafore\n" );
-        exit( 1 );
-    }
-    else
-    {
-        printf("\n[ksh] %d for fft\n", i );
-    }
-    strcpy( buf , "load /bin/user/fft.elf" );
-    parse( buf );
+
+/* To lauch one application without interactive mode
+   
+if( sem_wait( &semaphore ) )
+{
+    printf("\n[ksh error] cannot found semafore\n" );
+    exit( 1 );
 }
+else
+{
+    printf("\n[ksh] for fft\n");
+}
+
+strcpy( buf , "load /bin/user/fft.elf" );
+parse( buf );
 
 */
@@ -1081,4 +1145,7 @@
 printf("\n[ksh] main launched interactive thread => wait children termination\n" ); 
 #endif
+
+    // signal INIT process
+    kill( 1 , SIGCONT );
     
     // enter infinite loop monitoring children processes termination 
