| 1 | ///////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 2 | // File   :  ksh.c | 
|---|
| 3 | // Date   :  October 2017 | 
|---|
| 4 | // Author :  Alain Greiner | 
|---|
| 5 | ///////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 6 | // This application implements a minimal shell for ALMOS-MKH. | 
|---|
| 7 | // | 
|---|
| 8 | // This user process contains two POSIX threads: | 
|---|
| 9 | // - the "main" thread contains the infinite loop implementing | 
|---|
| 10 | //   the children processes termination monitoring, using the wait() syscall. | 
|---|
| 11 | // - the "interactive" thread contains the infinite loop implementing the command | 
|---|
| 12 | //   interpreter attached to the TXT terminal, and handling one KSH command | 
|---|
| 13 | //   per iteration.  | 
|---|
| 14 | // | 
|---|
| 15 | // The children processes are created by the <load> command, and are | 
|---|
| 16 | // attached to the same TXT terminal as the parent KSH process. | 
|---|
| 17 | // A child process can be launched in foreground or in background:  | 
|---|
| 18 | // . when the child process is launched in foreground, the KSH process loses | 
|---|
| 19 | //   the TXT terminal ownership, that is transfered to the child process. | 
|---|
| 20 | // . when the child process is launched in background, the KSH process keeps | 
|---|
| 21 | //   the TXT terminal ownership. | 
|---|
| 22 | // | 
|---|
| 23 | // We use a semaphore to synchronize the two KSH threads. After each command | 
|---|
| 24 | // completion, the interactive thread check the TXT ownership (with a sem_wait), | 
|---|
| 25 | // and blocks, if the KSH process loosed the TXT ownership (after a load, | 
|---|
| 26 | // or for any other cause). It is unblocked with the following policy: | 
|---|
| 27 | // . if the command is "not a load", the semaphore is incremented by the  | 
|---|
| 28 | //   cmd_***() function when the command is completed, to get the next command  | 
|---|
| 29 | //   in the while loop.     | 
|---|
| 30 | // . if the command is a "load without &", the TXT is given to the NEW process by the | 
|---|
| 31 | //   execve() syscall, and is released to the KSH process when NEW process terminates. | 
|---|
| 32 | //   The KSH process is notified and the KSH main() function increments the semahore  | 
|---|
| 33 | //   to allow the KSH interactive() function to handle commands. | 
|---|
| 34 | // . if the command is a "load with &", the cmd_load() function returns the TXT  | 
|---|
| 35 | //   to the KSH process and increment the semaphore, when the parent KSH process  | 
|---|
| 36 | //   returns from the fork() syscall. | 
|---|
| 37 | ///////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 38 |  | 
|---|
| 39 | #include <stdio.h> | 
|---|
| 40 | #include <stdlib.h> | 
|---|
| 41 | #include <string.h> | 
|---|
| 42 | #include <sys/wait.h> | 
|---|
| 43 | #include <signal.h> | 
|---|
| 44 | #include <unistd.h> | 
|---|
| 45 | #include <dirent.h> | 
|---|
| 46 | #include <almosmkh.h> | 
|---|
| 47 | #include <semaphore.h> | 
|---|
| 48 | #include <hal_macros.h> | 
|---|
| 49 | #include <sys/stat.h> | 
|---|
| 50 | #include <sys/mman.h> | 
|---|
| 51 | #include <fcntl.h> | 
|---|
| 52 | #include <shared_syscalls.h> | 
|---|
| 53 |  | 
|---|
| 54 | #define CMD_MAX_SIZE       (256)    // max number of characters in one command | 
|---|
| 55 | #define LOG_DEPTH          (32)     // max number of registered commands  | 
|---|
| 56 | #define MAX_ARGS               (32)     // max number of arguments in a command | 
|---|
| 57 | #define PATH_MAX_SIZE      (256)    // max number of characters in a pathname  | 
|---|
| 58 |  | 
|---|
| 59 | #define DEBUG_MAIN          0 | 
|---|
| 60 | #define DEBUG_INTER         0 | 
|---|
| 61 | #define DEBUG_EXECUTE       0 | 
|---|
| 62 | #define DEBUG_CMD_CAT       0 | 
|---|
| 63 | #define DEBUG_CMD_CP        0 | 
|---|
| 64 | #define DEBUG_CMD_LOAD      0 | 
|---|
| 65 | #define DEBUG_CMD_LS        0 | 
|---|
| 66 | #define DEBUG_CMD_PS        0 | 
|---|
| 67 |  | 
|---|
| 68 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 69 | //         Structures | 
|---|
| 70 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 71 |  | 
|---|
| 72 | // one entry in the registered commands array | 
|---|
| 73 | typedef struct log_entry_s  | 
|---|
| 74 | { | 
|---|
| 75 |         char          buf[CMD_MAX_SIZE]; | 
|---|
| 76 |         unsigned int  count; | 
|---|
| 77 | } | 
|---|
| 78 | log_entry_t; | 
|---|
| 79 |  | 
|---|
| 80 | // one entry in the supported command types array | 
|---|
| 81 | typedef struct ksh_cmd_s  | 
|---|
| 82 | { | 
|---|
| 83 |         char * name; | 
|---|
| 84 |         char * desc; | 
|---|
| 85 |         void   (*fn)( int , char ** ); | 
|---|
| 86 | } | 
|---|
| 87 | ksh_cmd_t; | 
|---|
| 88 |  | 
|---|
| 89 |  | 
|---|
| 90 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 91 | //         Global Variables | 
|---|
| 92 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 93 |  | 
|---|
| 94 | ksh_cmd_t       command[];                  // array of supported commands | 
|---|
| 95 |  | 
|---|
| 96 | log_entry_t     log_entries[LOG_DEPTH];     // array of registered commands | 
|---|
| 97 |  | 
|---|
| 98 | unsigned int    ptw;                        // write pointer in log_entries[] | 
|---|
| 99 | unsigned int    ptr;                        // read pointer in log_entries[] | 
|---|
| 100 |  | 
|---|
| 101 | pthread_attr_t  attr;                       // interactive thread attributes | 
|---|
| 102 |  | 
|---|
| 103 | sem_t           semaphore;                  // block interactive thread when zero | 
|---|
| 104 |  | 
|---|
| 105 | pthread_t       trdid;                      // interactive thread identifier | 
|---|
| 106 |  | 
|---|
| 107 | char            pathname[PATH_MAX_SIZE];    // pathname for a file | 
|---|
| 108 |  | 
|---|
| 109 | char            pathnew[PATH_MAX_SIZE];     // used by the rename command | 
|---|
| 110 |   | 
|---|
| 111 | char            string[128];                // used by snprintf() for debug | 
|---|
| 112 |  | 
|---|
| 113 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 114 | //         Shell  Commands | 
|---|
| 115 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 116 |  | 
|---|
| 117 | ///////////////////////////////////////////// | 
|---|
| 118 | static void cmd_cat( int argc , char **argv ) | 
|---|
| 119 | { | 
|---|
| 120 |     struct stat    st; | 
|---|
| 121 |     int            fd; | 
|---|
| 122 |     int            size; | 
|---|
| 123 |     char         * buf; | 
|---|
| 124 |  | 
|---|
| 125 | #if DEBUG_CMD_CAT | 
|---|
| 126 | snprintf( string , 128 , "[ksh] %s enters" , __FUNCTION__); | 
|---|
| 127 | display_string( string ); | 
|---|
| 128 | #endif | 
|---|
| 129 |  | 
|---|
| 130 |         if (argc != 2)  | 
|---|
| 131 |     { | 
|---|
| 132 |                 printf("  usage: cat pathname\n"); | 
|---|
| 133 |  | 
|---|
| 134 |         sem_post( &semaphore ); | 
|---|
| 135 |             return; | 
|---|
| 136 |     } | 
|---|
| 137 |  | 
|---|
| 138 |     strcpy( pathname , argv[1] ); | 
|---|
| 139 |  | 
|---|
| 140 | #if DEBUG_CMD_CAT | 
|---|
| 141 | snprintf( string , 128 , "[ksh] %s : after strcpy" , __FUNCTION__ ); | 
|---|
| 142 | display_string( string ); | 
|---|
| 143 | #endif | 
|---|
| 144 |  | 
|---|
| 145 |     // open the file | 
|---|
| 146 |     fd = open( pathname , O_RDONLY , 0 ); | 
|---|
| 147 |     if (fd < 0)  | 
|---|
| 148 |     { | 
|---|
| 149 |             printf("  error: cannot open file <%s>\n", pathname ); | 
|---|
| 150 |  | 
|---|
| 151 |         sem_post( &semaphore ); | 
|---|
| 152 |             return; | 
|---|
| 153 |     } | 
|---|
| 154 |  | 
|---|
| 155 | #if DEBUG_CMD_CAT | 
|---|
| 156 | snprintf( string , 128 , "[ksh] %s : file %s open", __FUNCTION__, pathname ); | 
|---|
| 157 | display_string( string ); | 
|---|
| 158 | #endif | 
|---|
| 159 |  | 
|---|
| 160 |     // get file stats  | 
|---|
| 161 |     if ( stat( pathname , &st ) == -1) | 
|---|
| 162 |     { | 
|---|
| 163 |             printf("  error: cannot stat <%s>\n", pathname ); | 
|---|
| 164 |  | 
|---|
| 165 |             close(fd); | 
|---|
| 166 |         sem_post( &semaphore ); | 
|---|
| 167 |             return; | 
|---|
| 168 |     } | 
|---|
| 169 |  | 
|---|
| 170 |         if ( S_ISDIR(st.st_mode) ) | 
|---|
| 171 |     { | 
|---|
| 172 |             printf("  error: <%s> is a directory\n", pathname ); | 
|---|
| 173 |  | 
|---|
| 174 |             close(fd); | 
|---|
| 175 |         sem_post( &semaphore ); | 
|---|
| 176 |             return; | 
|---|
| 177 |     } | 
|---|
| 178 |  | 
|---|
| 179 |     // get file size | 
|---|
| 180 |     size = st.st_size; | 
|---|
| 181 |  | 
|---|
| 182 | #if DEBUG_CMD_CAT | 
|---|
| 183 | snprintf( string , 128 , "[ksh] %s : size = %d", | 
|---|
| 184 | __FUNCTION__, size ); | 
|---|
| 185 | display_string( string ); | 
|---|
| 186 | #endif | 
|---|
| 187 |  | 
|---|
| 188 |     if( size == 0 ) | 
|---|
| 189 |     { | 
|---|
| 190 |             printf("  error: size = 0 for <%s>\n", pathname ); | 
|---|
| 191 |  | 
|---|
| 192 |             close(fd); | 
|---|
| 193 |         sem_post( &semaphore ); | 
|---|
| 194 |             return; | 
|---|
| 195 |     } | 
|---|
| 196 |  | 
|---|
| 197 |     // mapping type is MAP_FILE when MAP_ANON and MAP_REMOTE are not specified | 
|---|
| 198 |     buf = mmap( NULL , size , PROT_READ|PROT_WRITE , MAP_PRIVATE , fd , 0 ); | 
|---|
| 199 |  | 
|---|
| 200 |     if ( buf == NULL ) | 
|---|
| 201 |     { | 
|---|
| 202 |             printf("  error: cannot map file <%s>\n", pathname ); | 
|---|
| 203 |  | 
|---|
| 204 |             close(fd); | 
|---|
| 205 |         sem_post( &semaphore ); | 
|---|
| 206 |             return; | 
|---|
| 207 |     } | 
|---|
| 208 |  | 
|---|
| 209 | #if DEBUG_CMD_CAT | 
|---|
| 210 | snprintf( string , 128 , "[ksh] %s : mapped file %d to buffer %x", | 
|---|
| 211 | __FUNCTION__, fd , buf ); | 
|---|
| 212 | display_string( string ); | 
|---|
| 213 | #endif | 
|---|
| 214 |  | 
|---|
| 215 |     // display the file content on TXT terminal | 
|---|
| 216 |     write( 1 , buf , size ); | 
|---|
| 217 |  | 
|---|
| 218 |     // unmap the file | 
|---|
| 219 |     if( munmap( buf , size ) ) | 
|---|
| 220 |     { | 
|---|
| 221 |             printf("  error: cannot unmap file <%s>\n", pathname ); | 
|---|
| 222 |     } | 
|---|
| 223 |  | 
|---|
| 224 | #if DEBUG_CMD_CAT | 
|---|
| 225 | snprintf( string , 128 , "[ksh] %s : unmapped file %d from buffer %x",  | 
|---|
| 226 | __FUNCTION__, fd , buf ); | 
|---|
| 227 | display_string( string ); | 
|---|
| 228 | #endif | 
|---|
| 229 |  | 
|---|
| 230 |     // close the file | 
|---|
| 231 |         if( close( fd ) ) | 
|---|
| 232 |     { | 
|---|
| 233 |             printf("  error: cannot close file <%s>\n", pathname ); | 
|---|
| 234 |     } | 
|---|
| 235 |  | 
|---|
| 236 |     // release semaphore to get next command | 
|---|
| 237 |     sem_post( &semaphore ); | 
|---|
| 238 |  | 
|---|
| 239 | }   // end cmd_cat() | 
|---|
| 240 |  | 
|---|
| 241 | //////////////////////////////////////////// | 
|---|
| 242 | static void cmd_cd( int argc , char **argv ) | 
|---|
| 243 | { | 
|---|
| 244 |         if (argc != 2) | 
|---|
| 245 |     { | 
|---|
| 246 |                 printf("  usage: cd pathname\n"); | 
|---|
| 247 |         } | 
|---|
| 248 |     else | 
|---|
| 249 |     { | 
|---|
| 250 |             strcpy( pathname , argv[1] ); | 
|---|
| 251 |  | 
|---|
| 252 |         // call the relevant syscall | 
|---|
| 253 |         if( chdir( pathname ) ) | 
|---|
| 254 |         { | 
|---|
| 255 |             printf("  error: cannot found <%s> directory\n", pathname ); | 
|---|
| 256 |         } | 
|---|
| 257 |     } | 
|---|
| 258 |  | 
|---|
| 259 |     // release semaphore to get next command | 
|---|
| 260 |     sem_post( &semaphore ); | 
|---|
| 261 |  | 
|---|
| 262 | }   // end cmd_cd() | 
|---|
| 263 |  | 
|---|
| 264 | ///////////////////////////////////////// | 
|---|
| 265 | static void cmd_cp(int argc, char **argv) | 
|---|
| 266 | { | 
|---|
| 267 |         int          src_fd; | 
|---|
| 268 |     int          dst_fd; | 
|---|
| 269 |         int          size;          // source file size | 
|---|
| 270 |         int          bytes;         // number of transfered bytes | 
|---|
| 271 |         char         buf[4096]; | 
|---|
| 272 |         struct stat  st; | 
|---|
| 273 |  | 
|---|
| 274 | #if DEBUG_CMD_CP | 
|---|
| 275 | snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__); | 
|---|
| 276 | display_string( string ); | 
|---|
| 277 | #endif | 
|---|
| 278 |  | 
|---|
| 279 |         if (argc != 3)  | 
|---|
| 280 |     { | 
|---|
| 281 |         src_fd = -1; | 
|---|
| 282 |         dst_fd = -1; | 
|---|
| 283 |                 printf("  usage: cp src_pathname dst_pathname\n"); | 
|---|
| 284 |         goto cmd_cp_exit; | 
|---|
| 285 |         } | 
|---|
| 286 |  | 
|---|
| 287 |     // open the src file  | 
|---|
| 288 |     strcpy( pathname , argv[1] ); | 
|---|
| 289 |     src_fd = open( pathname , O_RDONLY , 0 ); | 
|---|
| 290 |  | 
|---|
| 291 |     if ( src_fd < 0 )  | 
|---|
| 292 |     { | 
|---|
| 293 |         dst_fd = -1; | 
|---|
| 294 |             printf("  error: cannot open <%s>\n", argv[1] ); | 
|---|
| 295 |             goto cmd_cp_exit; | 
|---|
| 296 |     } | 
|---|
| 297 |  | 
|---|
| 298 | #if DEBUG_CMD_CP | 
|---|
| 299 | snprintf( string , 128 , "[ksh] %s : file %s open", __FUNCTION__, argv[1] ); | 
|---|
| 300 | display_string( string ); | 
|---|
| 301 | #endif | 
|---|
| 302 |  | 
|---|
| 303 |     // get file stats | 
|---|
| 304 |     if ( stat( pathname , &st ) ) | 
|---|
| 305 |     { | 
|---|
| 306 |         dst_fd = -1; | 
|---|
| 307 |             printf("  error: cannot stat <%s>\n", argv[1] ); | 
|---|
| 308 |             goto cmd_cp_exit; | 
|---|
| 309 |     } | 
|---|
| 310 |  | 
|---|
| 311 | #if DEBUG_CMD_CP | 
|---|
| 312 | snprintf( string , 128 , "[ksh] %s : got stats for %s", __FUNCTION__, argv[1] ); | 
|---|
| 313 | display_string( string ); | 
|---|
| 314 | #endif | 
|---|
| 315 |  | 
|---|
| 316 |         if ( S_ISDIR(st.st_mode) ) | 
|---|
| 317 |     { | 
|---|
| 318 |         dst_fd = -1; | 
|---|
| 319 |                 printf("  error: <%s> is a directory\n", argv[1] ); | 
|---|
| 320 |                 goto cmd_cp_exit; | 
|---|
| 321 |         } | 
|---|
| 322 |  | 
|---|
| 323 |     // get src file size | 
|---|
| 324 |         size = st.st_size; | 
|---|
| 325 |  | 
|---|
| 326 |         // open the dst file  | 
|---|
| 327 |     strcpy( pathname , argv[2] ); | 
|---|
| 328 |         dst_fd = open( pathname , O_CREAT|O_TRUNC|O_RDWR , 0 ); | 
|---|
| 329 |  | 
|---|
| 330 |         if ( dst_fd < 0 )  | 
|---|
| 331 |     { | 
|---|
| 332 |                 printf("  error: cannot open <%s>\n", argv[2] ); | 
|---|
| 333 |                 goto cmd_cp_exit; | 
|---|
| 334 |         } | 
|---|
| 335 |  | 
|---|
| 336 | #if DEBUG_CMD_CP | 
|---|
| 337 | snprintf( string , 128 , "[ksh] %s : file %s open", __FUNCTION__, argv[2] ); | 
|---|
| 338 | display_string( string ); | 
|---|
| 339 | #endif | 
|---|
| 340 |  | 
|---|
| 341 |         if ( stat( pathname , &st ) ) | 
|---|
| 342 |     { | 
|---|
| 343 |                 printf("  error: cannot stat <%s>\n", argv[2] ); | 
|---|
| 344 |                 goto cmd_cp_exit; | 
|---|
| 345 |         } | 
|---|
| 346 |  | 
|---|
| 347 | #if DEBUG_CMD_CP | 
|---|
| 348 | snprintf( string , 128 , "[ksh] %s : got stats for %s", __FUNCTION__, argv[2] ); | 
|---|
| 349 | display_string( string ); | 
|---|
| 350 | #endif | 
|---|
| 351 |  | 
|---|
| 352 |         if ( S_ISDIR(st.st_mode ) )  | 
|---|
| 353 |     { | 
|---|
| 354 |                 printf("  error: <%s> is a directory\n", argv[2] ); | 
|---|
| 355 |                 goto cmd_cp_exit; | 
|---|
| 356 |         } | 
|---|
| 357 |  | 
|---|
| 358 |         bytes = 0; | 
|---|
| 359 |  | 
|---|
| 360 |         while (bytes < size) | 
|---|
| 361 |         { | 
|---|
| 362 |                 int len = ((size - bytes) < 4096) ? (size - bytes) : 4096; | 
|---|
| 363 |  | 
|---|
| 364 |                 // read the source  | 
|---|
| 365 |                 if ( read( src_fd , buf , len ) != len ) | 
|---|
| 366 |         { | 
|---|
| 367 |                         printf("  error: cannot read from file <%s>\n", argv[1] ); | 
|---|
| 368 |                         goto cmd_cp_exit; | 
|---|
| 369 |                 } | 
|---|
| 370 |  | 
|---|
| 371 | #if DEBUG_CMD_CP | 
|---|
| 372 | snprintf( string , 128 , "[ksh] %s : read %d bytes from %s", __FUNCTION__, len, argv[1] ); | 
|---|
| 373 | display_string( string ); | 
|---|
| 374 | #endif | 
|---|
| 375 |  | 
|---|
| 376 |                 // write to the destination  | 
|---|
| 377 |                 if ( write( dst_fd , buf , len ) != len ) | 
|---|
| 378 |         { | 
|---|
| 379 |                         printf("  error: cannot write to file <%s>\n", argv[2] ); | 
|---|
| 380 |                         goto cmd_cp_exit; | 
|---|
| 381 |                 } | 
|---|
| 382 |  | 
|---|
| 383 | #if DEBUG_CMD_CP | 
|---|
| 384 | snprintf( string , 128 , "[ksh] %s : write %d bytes to %s", __FUNCTION__, len, argv[2] ); | 
|---|
| 385 | display_string( string ); | 
|---|
| 386 | #endif | 
|---|
| 387 |  | 
|---|
| 388 |                 bytes += len; | 
|---|
| 389 |         } | 
|---|
| 390 |  | 
|---|
| 391 | cmd_cp_exit: | 
|---|
| 392 |  | 
|---|
| 393 |         if (src_fd >= 0) close(src_fd); | 
|---|
| 394 |         if (dst_fd >= 0) close(dst_fd); | 
|---|
| 395 |  | 
|---|
| 396 |     // release semaphore to get next command | 
|---|
| 397 |     sem_post( &semaphore ); | 
|---|
| 398 |  | 
|---|
| 399 | }   // end cmd_cp() | 
|---|
| 400 |  | 
|---|
| 401 | ///////////////////////////////////////////////// | 
|---|
| 402 | static void cmd_display( int argc , char **argv ) | 
|---|
| 403 | { | 
|---|
| 404 |     if( argc < 2 ) | 
|---|
| 405 |     { | 
|---|
| 406 |         printf("  usage: display  vmm      cxy      pid      mapping\n" | 
|---|
| 407 |                "         display  sched    cxy      lid\n"               | 
|---|
| 408 |                "         display  process  cxy\n"               | 
|---|
| 409 |                "         display  txt      txtid\n"               | 
|---|
| 410 |                "         display  vfs\n"               | 
|---|
| 411 |                "         display  chdev\n"               | 
|---|
| 412 |                "         display  dqdt\n"               | 
|---|
| 413 |                "         display  locks    pid      trdid\n" | 
|---|
| 414 |                "         display  barrier  pid\n" | 
|---|
| 415 |                "         display  mapper   path     page     nbytes\n" | 
|---|
| 416 |                "         display  fat      min      nslots\n" | 
|---|
| 417 |                "         display  fat      cxy      0\n" | 
|---|
| 418 |                "         display  socket   pid      fdid\n" ); | 
|---|
| 419 |     } | 
|---|
| 420 |     //////////////////////////////////// | 
|---|
| 421 |     else if( strcmp( argv[1] , "vmm" ) == 0 ) | 
|---|
| 422 |     { | 
|---|
| 423 |         if( argc != 5 ) | 
|---|
| 424 |         { | 
|---|
| 425 |                     printf("  usage: display vmm cxy pid mapping\n"); | 
|---|
| 426 |             } | 
|---|
| 427 |         else | 
|---|
| 428 |         { | 
|---|
| 429 |                 unsigned int cxy = atoi(argv[2]); | 
|---|
| 430 |                 unsigned int pid = atoi(argv[3]); | 
|---|
| 431 |                 unsigned int map = atoi(argv[4]); | 
|---|
| 432 |  | 
|---|
| 433 |             if( display_vmm( cxy , pid , map ) ) | 
|---|
| 434 |             { | 
|---|
| 435 |                 printf("  error: no process %x in cluster %x\n", pid , cxy ); | 
|---|
| 436 |             } | 
|---|
| 437 |         } | 
|---|
| 438 |     } | 
|---|
| 439 |     /////////////////////////////////////////// | 
|---|
| 440 |     else if( strcmp( argv[1] , "sched" ) == 0 ) | 
|---|
| 441 |     { | 
|---|
| 442 |         if( argc != 4 ) | 
|---|
| 443 |         { | 
|---|
| 444 |                     printf("  usage: display sched cxy lid\n"); | 
|---|
| 445 |             } | 
|---|
| 446 |         else | 
|---|
| 447 |         { | 
|---|
| 448 |                 unsigned int cxy = atoi(argv[2]); | 
|---|
| 449 |                 unsigned int lid = atoi(argv[3]); | 
|---|
| 450 |  | 
|---|
| 451 |             if( display_sched( cxy , lid ) ) | 
|---|
| 452 |             { | 
|---|
| 453 |                 printf("  error: illegal arguments cxy = %x / lid = %d\n", cxy, lid ); | 
|---|
| 454 |             } | 
|---|
| 455 |         } | 
|---|
| 456 |     } | 
|---|
| 457 |     ///////////////////////////////////////////// | 
|---|
| 458 |     else if( strcmp( argv[1] , "process" ) == 0 ) | 
|---|
| 459 |     { | 
|---|
| 460 |         if( argc != 3 ) | 
|---|
| 461 |         { | 
|---|
| 462 |                     printf("  usage: display process cxy\n"); | 
|---|
| 463 |             } | 
|---|
| 464 |         else | 
|---|
| 465 |         { | 
|---|
| 466 |                 unsigned int cxy = atoi(argv[2]); | 
|---|
| 467 |  | 
|---|
| 468 |             if( display_cluster_processes( cxy , 0 ) ) | 
|---|
| 469 |             { | 
|---|
| 470 |                 printf("  error: illegal argument cxy = %x\n", cxy ); | 
|---|
| 471 |             } | 
|---|
| 472 |         } | 
|---|
| 473 |     } | 
|---|
| 474 |     ///////////////////////////////////////// | 
|---|
| 475 |     else if( strcmp( argv[1] , "txt" ) == 0 ) | 
|---|
| 476 |     { | 
|---|
| 477 |         if( argc != 3 ) | 
|---|
| 478 |         { | 
|---|
| 479 |                     printf("  usage: display txt txt_id\n"); | 
|---|
| 480 |             } | 
|---|
| 481 |         else | 
|---|
| 482 |         { | 
|---|
| 483 |                 unsigned int txtid = atoi(argv[2]); | 
|---|
| 484 |  | 
|---|
| 485 |             if( display_txt_processes( txtid ) ) | 
|---|
| 486 |             { | 
|---|
| 487 |                 printf("  error: illegal argument txtid = %d\n", txtid ); | 
|---|
| 488 |             } | 
|---|
| 489 |         } | 
|---|
| 490 |     } | 
|---|
| 491 |     ///////////////////////////////////////// | 
|---|
| 492 |     else if( strcmp( argv[1] , "vfs" ) == 0 ) | 
|---|
| 493 |     { | 
|---|
| 494 |         if( argc != 2 ) | 
|---|
| 495 |         { | 
|---|
| 496 |                     printf("  usage: display vfs\n"); | 
|---|
| 497 |             } | 
|---|
| 498 |         else | 
|---|
| 499 |         { | 
|---|
| 500 |             display_vfs(); | 
|---|
| 501 |         } | 
|---|
| 502 |     } | 
|---|
| 503 |     ////////////////////////////////////////// | 
|---|
| 504 |     else if( strcmp( argv[1] , "chdev" ) == 0 ) | 
|---|
| 505 |     { | 
|---|
| 506 |         if( argc != 2 ) | 
|---|
| 507 |         { | 
|---|
| 508 |                     printf("  usage: display chdev\n"); | 
|---|
| 509 |             } | 
|---|
| 510 |         else | 
|---|
| 511 |         { | 
|---|
| 512 |             display_chdev(); | 
|---|
| 513 |         } | 
|---|
| 514 |     } | 
|---|
| 515 |     ////////////////////////////////////////// | 
|---|
| 516 |     else if( strcmp( argv[1] , "dqdt" ) == 0 ) | 
|---|
| 517 |     { | 
|---|
| 518 |         if( argc != 2 ) | 
|---|
| 519 |         { | 
|---|
| 520 |                     printf("  usage: display dqdt\n"); | 
|---|
| 521 |             } | 
|---|
| 522 |         else | 
|---|
| 523 |         { | 
|---|
| 524 |             display_dqdt(); | 
|---|
| 525 |         } | 
|---|
| 526 |     } | 
|---|
| 527 |     /////////////////////////////////////////// | 
|---|
| 528 |     else if( strcmp( argv[1] , "locks" ) == 0 ) | 
|---|
| 529 |     { | 
|---|
| 530 |         if( argc != 4 ) | 
|---|
| 531 |         { | 
|---|
| 532 |                     printf("  usage: display locks pid trdid\n"); | 
|---|
| 533 |             } | 
|---|
| 534 |         else | 
|---|
| 535 |         { | 
|---|
| 536 |                 unsigned int pid   = atoi(argv[2]); | 
|---|
| 537 |             unsigned int trdid = atoi(argv[3]); | 
|---|
| 538 |  | 
|---|
| 539 |             if( display_busylocks( pid , trdid ) ) | 
|---|
| 540 |             { | 
|---|
| 541 |                 printf("  error: illegal arguments pid = %x / trdid = %x\n", pid, trdid ); | 
|---|
| 542 |             } | 
|---|
| 543 |         } | 
|---|
| 544 |     } | 
|---|
| 545 |     ///////////////////////////////////////////////// | 
|---|
| 546 |     else if( strcmp( argv[1] , "barrier" ) == 0 ) | 
|---|
| 547 |     { | 
|---|
| 548 |         if( argc != 3 ) | 
|---|
| 549 |         { | 
|---|
| 550 |                     printf("  usage: display barrier pid\n"); | 
|---|
| 551 |             } | 
|---|
| 552 |         else | 
|---|
| 553 |         { | 
|---|
| 554 |                 unsigned int pid   = atoi(argv[2]); | 
|---|
| 555 |  | 
|---|
| 556 |             if( display_barrier( pid ) ) | 
|---|
| 557 |             { | 
|---|
| 558 |                 printf("  error: illegal arguments pid = %x\n", pid ); | 
|---|
| 559 |             } | 
|---|
| 560 |         } | 
|---|
| 561 |     } | 
|---|
| 562 |     /////////////////////////////////////////// | 
|---|
| 563 |     else if( strcmp( argv[1] , "mapper" ) == 0 ) | 
|---|
| 564 |     { | 
|---|
| 565 |         if( argc != 5 ) | 
|---|
| 566 |         { | 
|---|
| 567 |                     printf("  usage: display mapper path page_id nbytes\n"); | 
|---|
| 568 |             } | 
|---|
| 569 |         else | 
|---|
| 570 |         { | 
|---|
| 571 |                 unsigned int page_id   = atoi(argv[3]); | 
|---|
| 572 |             unsigned int nbytes    = atoi(argv[4]); | 
|---|
| 573 |  | 
|---|
| 574 |             if( display_mapper( argv[2] , page_id, nbytes ) ) | 
|---|
| 575 |             { | 
|---|
| 576 |                 printf("  error: cannot display page %d of mapper %s\n", page_id, argv[2] ); | 
|---|
| 577 |             } | 
|---|
| 578 |         } | 
|---|
| 579 |     } | 
|---|
| 580 |     /////////////////////////////////////////// | 
|---|
| 581 |     else if( strcmp( argv[1] , "fat" ) == 0 ) | 
|---|
| 582 |     { | 
|---|
| 583 |         if( argc != 4 ) | 
|---|
| 584 |         { | 
|---|
| 585 |                     printf("  usage: display fat  min_slot  nb_slots\n"); | 
|---|
| 586 |             } | 
|---|
| 587 |         else | 
|---|
| 588 |         { | 
|---|
| 589 |                 unsigned int min_slot = atoi(argv[2]); | 
|---|
| 590 |             unsigned int nb_slots = atoi(argv[3]); | 
|---|
| 591 |  | 
|---|
| 592 |             if( display_fat( min_slot, nb_slots ) ) | 
|---|
| 593 |             { | 
|---|
| 594 |                 printf("  error: cannot display fat\n"); | 
|---|
| 595 |             } | 
|---|
| 596 |         } | 
|---|
| 597 |     } | 
|---|
| 598 |     /////////////////////////////////////////// | 
|---|
| 599 |     else if( strcmp( argv[1] , "socket" ) == 0 ) | 
|---|
| 600 |     { | 
|---|
| 601 |         if( argc != 4 ) | 
|---|
| 602 |         { | 
|---|
| 603 |                     printf("  usage: display socket pid fdid\n"); | 
|---|
| 604 |             } | 
|---|
| 605 |         else | 
|---|
| 606 |         { | 
|---|
| 607 |                 unsigned int pid   = atoi(argv[2]); | 
|---|
| 608 |             unsigned int fdid = atoi(argv[3]); | 
|---|
| 609 |  | 
|---|
| 610 |             if( display_socket( pid , fdid ) ) | 
|---|
| 611 |             { | 
|---|
| 612 |                 printf("  error: cannot found socket[%x,%d]\n", pid, fdid ); | 
|---|
| 613 |             } | 
|---|
| 614 |         } | 
|---|
| 615 |     } | 
|---|
| 616 |     //// | 
|---|
| 617 |     else | 
|---|
| 618 |     { | 
|---|
| 619 |         printf("  error: undefined display request : %s\n", argv[1] );  | 
|---|
| 620 |     }         | 
|---|
| 621 |  | 
|---|
| 622 |     // release semaphore to get next command | 
|---|
| 623 |     sem_post( &semaphore ); | 
|---|
| 624 |  | 
|---|
| 625 | } // end cmd_display() | 
|---|
| 626 |  | 
|---|
| 627 | ///////////////////////////////////////// | 
|---|
| 628 | static void cmd_fg(int argc, char **argv) | 
|---|
| 629 | { | 
|---|
| 630 |         unsigned int pid; | 
|---|
| 631 |  | 
|---|
| 632 |         if (argc != 2)  | 
|---|
| 633 |     { | 
|---|
| 634 |                 printf("  usage: %s pid\n", argv[0]); | 
|---|
| 635 |         } | 
|---|
| 636 |     else | 
|---|
| 637 |     { | 
|---|
| 638 |         pid = atoi( argv[1] );    | 
|---|
| 639 |  | 
|---|
| 640 |         if( pid == 0 ) | 
|---|
| 641 |         {   | 
|---|
| 642 |                     printf("  error: PID cannot be 0\n" ); | 
|---|
| 643 |             } | 
|---|
| 644 |         else if( fg( pid ) ) | 
|---|
| 645 |         { | 
|---|
| 646 |                     printf("  error: cannot find process %x\n", pid ); | 
|---|
| 647 |             } | 
|---|
| 648 |     } | 
|---|
| 649 |  | 
|---|
| 650 |     // release semaphore to get next command | 
|---|
| 651 |     sem_post( &semaphore ); | 
|---|
| 652 |  | 
|---|
| 653 | }  // end cmd_fg() | 
|---|
| 654 |  | 
|---|
| 655 | ////////////////////////////////////////////// | 
|---|
| 656 | static void cmd_help( int argc , char **argv ) | 
|---|
| 657 | { | 
|---|
| 658 |         unsigned int i; | 
|---|
| 659 |  | 
|---|
| 660 |         if (argc != 1)  | 
|---|
| 661 |     { | 
|---|
| 662 |                 printf("  usage: %s\n", argv[0]); | 
|---|
| 663 |         } | 
|---|
| 664 |     else | 
|---|
| 665 |     { | 
|---|
| 666 |         printf("available commands:\n"); | 
|---|
| 667 |             for (i = 0 ; command[i].name ; i++)  | 
|---|
| 668 |         { | 
|---|
| 669 |                     printf("\t%s\t : %s\n", command[i].name , command[i].desc); | 
|---|
| 670 |             } | 
|---|
| 671 |     } | 
|---|
| 672 |  | 
|---|
| 673 |     // release semaphore to get next command | 
|---|
| 674 |     sem_post( &semaphore ); | 
|---|
| 675 |  | 
|---|
| 676 | }   // end cmd_help() | 
|---|
| 677 |  | 
|---|
| 678 | ////////////////////////////////////////////// | 
|---|
| 679 | static void cmd_kill( int argc , char **argv ) | 
|---|
| 680 | { | 
|---|
| 681 |         unsigned int pid; | 
|---|
| 682 |  | 
|---|
| 683 |         if (argc != 2)  | 
|---|
| 684 |     { | 
|---|
| 685 |                 printf("  usage: %s pid\n", argv[0]); | 
|---|
| 686 |         } | 
|---|
| 687 |     else | 
|---|
| 688 |     { | 
|---|
| 689 |             pid = atoi( argv[1] ); | 
|---|
| 690 |  | 
|---|
| 691 |         if( pid == 0 ) | 
|---|
| 692 |         { | 
|---|
| 693 |                     printf("  error: kernel process 0 cannot be killed\n" ); | 
|---|
| 694 |             } | 
|---|
| 695 |  | 
|---|
| 696 |             else if( kill( pid , SIGKILL ) ) | 
|---|
| 697 |         { | 
|---|
| 698 |                     printf("  error: process %x cannot be killed\n", pid ); | 
|---|
| 699 |             } | 
|---|
| 700 |     } | 
|---|
| 701 |  | 
|---|
| 702 |     // release semaphore to get next command | 
|---|
| 703 |     sem_post( &semaphore ); | 
|---|
| 704 |  | 
|---|
| 705 | }   // end cmd_kill() | 
|---|
| 706 |  | 
|---|
| 707 | ////////////////////////////////////////////// | 
|---|
| 708 | static void cmd_load( int argc , char **argv ) | 
|---|
| 709 | { | 
|---|
| 710 |         int                  ret_fork;           // return value from fork  | 
|---|
| 711 |         int                  ret_exec;           // return value from exec | 
|---|
| 712 |     unsigned int         ksh_pid;            // KSH process PID | 
|---|
| 713 |     unsigned int         background;         // background execution if non zero | 
|---|
| 714 |     unsigned int         placement;          // placement specified if non zero | 
|---|
| 715 |     unsigned int         cxy;                // target cluster if placement specified | 
|---|
| 716 |  | 
|---|
| 717 | #if DEBUG_CMD_LOAD | 
|---|
| 718 | snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__); | 
|---|
| 719 | display_string( string ); | 
|---|
| 720 | #endif | 
|---|
| 721 |  | 
|---|
| 722 |         if( (argc < 2) || (argc > 4) )   | 
|---|
| 723 |     { | 
|---|
| 724 |                 printf("  usage: %s pathname [cxy] [&]\n", argv[0] ); | 
|---|
| 725 |         } | 
|---|
| 726 |     else | 
|---|
| 727 |     { | 
|---|
| 728 |             strcpy( pathname , argv[1] ); | 
|---|
| 729 |  | 
|---|
| 730 |         if( argc == 2 ) | 
|---|
| 731 |         { | 
|---|
| 732 |             background = 0; | 
|---|
| 733 |             placement  = 0; | 
|---|
| 734 |             cxy        = 0; | 
|---|
| 735 |         } | 
|---|
| 736 |         else if( argc == 3 ) | 
|---|
| 737 |         { | 
|---|
| 738 |             if( (argv[2][0] == '&') && (argv[2][1] == 0) ) | 
|---|
| 739 |             { | 
|---|
| 740 |                 background = 1; | 
|---|
| 741 |                 placement  = 0; | 
|---|
| 742 |                 cxy        = 0; | 
|---|
| 743 |             } | 
|---|
| 744 |             else  | 
|---|
| 745 |             { | 
|---|
| 746 |                 background = 0; | 
|---|
| 747 |                 placement  = 1; | 
|---|
| 748 |                 cxy        = atoi( argv[2] ); | 
|---|
| 749 |             } | 
|---|
| 750 |         } | 
|---|
| 751 |         else  // argc == 4 | 
|---|
| 752 |         {  | 
|---|
| 753 |             background = ( (argv[3][0] == '&') && (argv[3][1] == 0) ); | 
|---|
| 754 |             placement  = 1; | 
|---|
| 755 |             cxy        = atoi( argv[2] ); | 
|---|
| 756 |         } | 
|---|
| 757 |  | 
|---|
| 758 |         // get KSH process PID | 
|---|
| 759 |         ksh_pid = getpid(); | 
|---|
| 760 |  | 
|---|
| 761 | #if DEBUG_CMD_LOAD | 
|---|
| 762 | snprintf( string , 128 , "[ksh] %s : <%s> / bg %d / place %d / cxy %x", | 
|---|
| 763 | __FUNCTION__, argv[1], background, placement, cxy ); | 
|---|
| 764 | display_string( string ); | 
|---|
| 765 | #endif | 
|---|
| 766 |  | 
|---|
| 767 |         // set target cluster if required | 
|---|
| 768 |         if( placement ) place_fork( cxy ); | 
|---|
| 769 |  | 
|---|
| 770 |         // KSH process fork CHILD process | 
|---|
| 771 |             ret_fork = fork(); | 
|---|
| 772 |  | 
|---|
| 773 |         if ( ret_fork < 0 )     // it is a failure reported to KSH | 
|---|
| 774 |         { | 
|---|
| 775 |             printf("  error: ksh process unable to fork\n"); | 
|---|
| 776 |         } | 
|---|
| 777 |         else if (ret_fork == 0) // it is the CHILD process  | 
|---|
| 778 |         { | 
|---|
| 779 |  | 
|---|
| 780 | #if DEBUG_CMD_LOAD | 
|---|
| 781 | snprintf( string , 128 , "[ksh] %s : child (%x) after fork, before exec", | 
|---|
| 782 | __FUNCTION__ , getpid() ); | 
|---|
| 783 | display_string( string ); | 
|---|
| 784 | #endif | 
|---|
| 785 |  | 
|---|
| 786 |             // CHILD process exec NEW process | 
|---|
| 787 |             ret_exec = execve( pathname , NULL , NULL ); | 
|---|
| 788 |  | 
|---|
| 789 | #if DEBUG_CMD_LOAD | 
|---|
| 790 | snprintf( string , 128 , "[ksh] %s : child (%x) after exec / ret_exec %x", | 
|---|
| 791 | __FUNCTION__ , getpid(), ret_exec ); | 
|---|
| 792 | display_string( string ); | 
|---|
| 793 | #endif | 
|---|
| 794 |  | 
|---|
| 795 |             // this is only executed in case of exec failure | 
|---|
| 796 |             if( ret_exec ) | 
|---|
| 797 |             { | 
|---|
| 798 |                 printf("  error: child process unable to exec <%s>\n", pathname ); | 
|---|
| 799 |                 exit( 0 ); | 
|---|
| 800 |             }    | 
|---|
| 801 |             }  | 
|---|
| 802 |         else                    // it is the KSH process : ret_fork is the new process PID | 
|---|
| 803 |         { | 
|---|
| 804 |  | 
|---|
| 805 | #if DEBUG_CMD_LOAD | 
|---|
| 806 | snprintf( string , 128 , "[ksh] %s : ksh (%x) after fork / ret_fork %x", | 
|---|
| 807 | __FUNCTION__, getpid(), ret_fork ); | 
|---|
| 808 | display_string( string ); | 
|---|
| 809 | #endif | 
|---|
| 810 |             // when the new process is launched in background, the KSH process  | 
|---|
| 811 |             // takes the TXT ownership, and release the semaphore to get the next command. | 
|---|
| 812 |             // Otherwise, the child process keep the TXT ownership, and the semaphore will | 
|---|
| 813 |             // be released by the KSH main thread when the child process exit | 
|---|
| 814 |  | 
|---|
| 815 |             if( background )    //  KSH must keep TXT ownership | 
|---|
| 816 |             { | 
|---|
| 817 |                 // get back the TXT ownership | 
|---|
| 818 |                 fg( ksh_pid ); | 
|---|
| 819 |  | 
|---|
| 820 |                 // release semaphore to get next command | 
|---|
| 821 |                 sem_post( &semaphore ); | 
|---|
| 822 |             } | 
|---|
| 823 |         } | 
|---|
| 824 |     } | 
|---|
| 825 | }   // end cmd_load | 
|---|
| 826 |  | 
|---|
| 827 | ///////////////////////////////////////////// | 
|---|
| 828 | static void cmd_log( int argc , char **argv ) | 
|---|
| 829 | { | 
|---|
| 830 |         unsigned int i; | 
|---|
| 831 |  | 
|---|
| 832 |         if (argc != 1) | 
|---|
| 833 |     { | 
|---|
| 834 |                 printf("  usage: %s\n", argv[0], argc );  | 
|---|
| 835 |         } | 
|---|
| 836 |     else | 
|---|
| 837 |     { | 
|---|
| 838 |             printf("--- registered commands ---\n"); | 
|---|
| 839 |             for (i = 0; i < LOG_DEPTH; i++)  | 
|---|
| 840 |         { | 
|---|
| 841 |                     printf(" - %d\t: %s\n", i, &log_entries[i].buf); | 
|---|
| 842 |             } | 
|---|
| 843 |     } | 
|---|
| 844 |  | 
|---|
| 845 |     // release semaphore to get next command | 
|---|
| 846 |     sem_post( &semaphore ); | 
|---|
| 847 |  | 
|---|
| 848 | } // end cmd_log() | 
|---|
| 849 |  | 
|---|
| 850 |  | 
|---|
| 851 | //////////////////////////////////////////// | 
|---|
| 852 | static void cmd_ls( int argc , char **argv ) | 
|---|
| 853 | { | 
|---|
| 854 |     struct dirent  * entry; | 
|---|
| 855 |     DIR            * dir; | 
|---|
| 856 |  | 
|---|
| 857 | #if DEBUG_CMD_LS | 
|---|
| 858 | snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__); | 
|---|
| 859 | display_string( string ); | 
|---|
| 860 | #endif | 
|---|
| 861 |  | 
|---|
| 862 |         if (argc > 2 ) | 
|---|
| 863 |     { | 
|---|
| 864 |                 printf("  usage: ls [path]\n"); | 
|---|
| 865 |         } | 
|---|
| 866 |     else | 
|---|
| 867 |     { | 
|---|
| 868 |         // handle case with no argument | 
|---|
| 869 |  | 
|---|
| 870 |         // get target directory path | 
|---|
| 871 |         if ( argc == 1 ) strcpy( pathname , "." ); | 
|---|
| 872 |         else             strcpy( pathname , argv[1] ); | 
|---|
| 873 |  | 
|---|
| 874 |         // open target directory | 
|---|
| 875 |             dir = opendir( pathname ); | 
|---|
| 876 |  | 
|---|
| 877 | #if DEBUG_CMD_LS | 
|---|
| 878 | snprintf( string , 128 , "[ksh] %s : directory <%s> open / DIR %x", | 
|---|
| 879 | __FUNCTION__, pathname , dir ); | 
|---|
| 880 | display_string( string ); | 
|---|
| 881 | #endif | 
|---|
| 882 |  | 
|---|
| 883 |         if( dir == NULL) | 
|---|
| 884 |             { | 
|---|
| 885 |                     printf("  error : directory <%s> not found\n", pathname ); | 
|---|
| 886 |  | 
|---|
| 887 |             sem_post( &semaphore ); | 
|---|
| 888 |             return; | 
|---|
| 889 |             } | 
|---|
| 890 |  | 
|---|
| 891 |         // loop on directory entries     | 
|---|
| 892 |         while ( (entry = readdir(dir)) != NULL ) | 
|---|
| 893 |             { | 
|---|
| 894 |                     printf("%s\n", entry->d_name); | 
|---|
| 895 |             } | 
|---|
| 896 |  | 
|---|
| 897 |         // close target directory | 
|---|
| 898 |             closedir( dir ); | 
|---|
| 899 |  | 
|---|
| 900 | #if DEBUG_CMD_LS | 
|---|
| 901 | snprintf( string , 128 , "[ksh] %s : directory <%s> closed", | 
|---|
| 902 | __FUNCTION__, pathname ); | 
|---|
| 903 | display_string( string ); | 
|---|
| 904 | #endif | 
|---|
| 905 |  | 
|---|
| 906 |     } | 
|---|
| 907 |  | 
|---|
| 908 |     // release semaphore to get next command | 
|---|
| 909 |     sem_post( &semaphore ); | 
|---|
| 910 |  | 
|---|
| 911 | } // end cmd_ls() | 
|---|
| 912 |  | 
|---|
| 913 | /////////////////////////////////////////////// | 
|---|
| 914 | static void cmd_mkdir( int argc , char **argv ) | 
|---|
| 915 | { | 
|---|
| 916 |         if (argc != 2) | 
|---|
| 917 |     { | 
|---|
| 918 |                 printf("  usage: mkdir pathname\n"); | 
|---|
| 919 |         } | 
|---|
| 920 |     else | 
|---|
| 921 |     { | 
|---|
| 922 |         strcpy( pathname , argv[1] ); | 
|---|
| 923 |  | 
|---|
| 924 |         mkdir( pathname , 0x777 ); | 
|---|
| 925 |     } | 
|---|
| 926 |  | 
|---|
| 927 |     // release semaphore to get next command | 
|---|
| 928 |     sem_post( &semaphore ); | 
|---|
| 929 |  | 
|---|
| 930 | } // end cmd_mkdir() | 
|---|
| 931 |  | 
|---|
| 932 | //////////////////////////////////////////// | 
|---|
| 933 | static void cmd_mv( int argc , char **argv ) | 
|---|
| 934 | { | 
|---|
| 935 |         if (argc != 3)  | 
|---|
| 936 |     { | 
|---|
| 937 |                 printf("  usage: mv old_pathname new_pathname\n"); | 
|---|
| 938 |         } | 
|---|
| 939 |     else | 
|---|
| 940 |     { | 
|---|
| 941 |         strcpy( pathname , argv[1] ); | 
|---|
| 942 |         strcpy( pathnew  , argv[2] ); | 
|---|
| 943 |  | 
|---|
| 944 |         // call the relevant syscall | 
|---|
| 945 |         if( rename( pathname , pathnew ) ) | 
|---|
| 946 |         { | 
|---|
| 947 |             printf("  error: unable to rename <%s> to <%s>\n", pathname , pathnew ); | 
|---|
| 948 |         } | 
|---|
| 949 |     } | 
|---|
| 950 |  | 
|---|
| 951 |     // release semaphore to get next command | 
|---|
| 952 |     sem_post( &semaphore ); | 
|---|
| 953 |  | 
|---|
| 954 | }  // end cmd_mv | 
|---|
| 955 |  | 
|---|
| 956 |  | 
|---|
| 957 | //////////////////////////////////////////// | 
|---|
| 958 | static void cmd_ps( int argc , char **argv ) | 
|---|
| 959 | { | 
|---|
| 960 |     unsigned int x_size; | 
|---|
| 961 |     unsigned int y_size; | 
|---|
| 962 |     unsigned int x; | 
|---|
| 963 |     unsigned int y; | 
|---|
| 964 |  | 
|---|
| 965 | #if DEBUG_CMD_PS | 
|---|
| 966 | snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__); | 
|---|
| 967 | display_string( string ); | 
|---|
| 968 | #endif | 
|---|
| 969 |  | 
|---|
| 970 |         if (argc != 1) | 
|---|
| 971 |     { | 
|---|
| 972 |                 printf("  usage: %s\n", argv[0]); | 
|---|
| 973 |         } | 
|---|
| 974 |     else | 
|---|
| 975 |     { | 
|---|
| 976 |         // get platform config | 
|---|
| 977 |         hard_config_t  config; | 
|---|
| 978 |         get_config( &config ); | 
|---|
| 979 |         x_size = config.x_size; | 
|---|
| 980 |         y_size = config.y_size; | 
|---|
| 981 |  | 
|---|
| 982 |         // scan all clusters | 
|---|
| 983 |         for( x = 0 ; x < x_size ; x++ ) | 
|---|
| 984 |         { | 
|---|
| 985 |             for( y = 0 ; y < y_size ; y++ ) | 
|---|
| 986 |             { | 
|---|
| 987 |  | 
|---|
| 988 | #if DEBUG_CMD_PS | 
|---|
| 989 | snprintf( string , 128 , "\n[ksh] %s : call display_cluster_process()", __FUNCTION__ ); | 
|---|
| 990 | display_string( string ); | 
|---|
| 991 | #endif | 
|---|
| 992 |  | 
|---|
| 993 |                 // display only owned processes | 
|---|
| 994 |                 display_cluster_processes( HAL_CXY_FROM_XY(x,y), 1 );  | 
|---|
| 995 |             } | 
|---|
| 996 |         } | 
|---|
| 997 |     } | 
|---|
| 998 |  | 
|---|
| 999 |     // release semaphore to get next command | 
|---|
| 1000 |     sem_post( &semaphore ); | 
|---|
| 1001 |  | 
|---|
| 1002 | }  // end cmd_ps() | 
|---|
| 1003 |  | 
|---|
| 1004 | ///////////////////////////////////////////// | 
|---|
| 1005 | static void cmd_pwd( int argc , char **argv ) | 
|---|
| 1006 | { | 
|---|
| 1007 |         if (argc != 1) | 
|---|
| 1008 |     { | 
|---|
| 1009 |                 printf("  usage: %s\n", argv[0]); | 
|---|
| 1010 |         } | 
|---|
| 1011 |     else  | 
|---|
| 1012 |     { | 
|---|
| 1013 |         if ( getcwd( pathname , PATH_MAX_SIZE ) )  | 
|---|
| 1014 |         { | 
|---|
| 1015 |                     printf("  error: unable to get current directory\n"); | 
|---|
| 1016 |             } | 
|---|
| 1017 |         else  | 
|---|
| 1018 |         { | 
|---|
| 1019 |                     printf("%s\n", pathname ); | 
|---|
| 1020 |             } | 
|---|
| 1021 |     } | 
|---|
| 1022 |  | 
|---|
| 1023 |     // release semaphore to get next command | 
|---|
| 1024 |     sem_post( &semaphore ); | 
|---|
| 1025 |  | 
|---|
| 1026 | }  // end cmd_pwd() | 
|---|
| 1027 |  | 
|---|
| 1028 | //////////////////////////////////////////// | 
|---|
| 1029 | static void cmd_rm( int argc , char **argv ) | 
|---|
| 1030 | { | 
|---|
| 1031 |         if (argc != 2) | 
|---|
| 1032 |     { | 
|---|
| 1033 |                 printf("  usage: %s pathname\n", argv[0]); | 
|---|
| 1034 |         } | 
|---|
| 1035 |     else | 
|---|
| 1036 |     { | 
|---|
| 1037 |             strcpy( pathname , argv[1] ); | 
|---|
| 1038 |  | 
|---|
| 1039 |         if ( unlink( pathname ) ) | 
|---|
| 1040 |         { | 
|---|
| 1041 |                     printf("  error: unable to remove <%s>\n", pathname ); | 
|---|
| 1042 |             } | 
|---|
| 1043 |     } | 
|---|
| 1044 |  | 
|---|
| 1045 |     // release semaphore to get next command | 
|---|
| 1046 |     sem_post( &semaphore ); | 
|---|
| 1047 |  | 
|---|
| 1048 | }  // end cmd_rm() | 
|---|
| 1049 |  | 
|---|
| 1050 | /////////////////////////////////////////////// | 
|---|
| 1051 | static void cmd_stat( int argc , char **argv ) | 
|---|
| 1052 | { | 
|---|
| 1053 |     struct stat    st; | 
|---|
| 1054 |     unsigned int   size; | 
|---|
| 1055 |  | 
|---|
| 1056 |         if (argc != 2) | 
|---|
| 1057 |     { | 
|---|
| 1058 |                 printf("  usage: %s pathname\n", argv[0]); | 
|---|
| 1059 |         } | 
|---|
| 1060 |     else | 
|---|
| 1061 |     { | 
|---|
| 1062 |             strcpy( pathname , argv[1] ); | 
|---|
| 1063 |  | 
|---|
| 1064 |         if ( stat( pathname , &st ) ) | 
|---|
| 1065 |         { | 
|---|
| 1066 |                     printf("  error: cannot stat <%s>\n", argv[2] ); | 
|---|
| 1067 |                 } | 
|---|
| 1068 |         else | 
|---|
| 1069 |         { | 
|---|
| 1070 |             // get file size | 
|---|
| 1071 |             size = st.st_size; | 
|---|
| 1072 |  | 
|---|
| 1073 |             // print file stat info | 
|---|
| 1074 |             printf("   <%s> : %d bytes\n", pathname, size ); | 
|---|
| 1075 |         } | 
|---|
| 1076 |         } | 
|---|
| 1077 |  | 
|---|
| 1078 |     // release semaphore to get next command | 
|---|
| 1079 |     sem_post( &semaphore ); | 
|---|
| 1080 |  | 
|---|
| 1081 | }  // end cmd_stat() | 
|---|
| 1082 |  | 
|---|
| 1083 | /////////////////////////////////////////////// | 
|---|
| 1084 | static void cmd_rmdir( int argc , char **argv ) | 
|---|
| 1085 | { | 
|---|
| 1086 |     // same as cmd_rm() | 
|---|
| 1087 |         cmd_rm (argc , argv ); | 
|---|
| 1088 | } | 
|---|
| 1089 |  | 
|---|
| 1090 | /////////////////////////////////////////////// | 
|---|
| 1091 | static void cmd_trace( int argc , char **argv ) | 
|---|
| 1092 | { | 
|---|
| 1093 |     unsigned int cxy; | 
|---|
| 1094 |     unsigned int lid; | 
|---|
| 1095 |  | 
|---|
| 1096 |         if (argc != 3) | 
|---|
| 1097 |     { | 
|---|
| 1098 |                 printf("  usage: trace cxy lid \n"); | 
|---|
| 1099 |         } | 
|---|
| 1100 |     else | 
|---|
| 1101 |     { | 
|---|
| 1102 |         cxy = atoi(argv[1]); | 
|---|
| 1103 |         lid = atoi(argv[2]); | 
|---|
| 1104 |  | 
|---|
| 1105 |         if( trace( 1 , cxy , lid ) ) | 
|---|
| 1106 |         { | 
|---|
| 1107 |             printf("  error: core[%x,%d] not found\n", cxy, lid ); | 
|---|
| 1108 |         } | 
|---|
| 1109 |     } | 
|---|
| 1110 |  | 
|---|
| 1111 |     // release semaphore to get next command | 
|---|
| 1112 |     sem_post( &semaphore ); | 
|---|
| 1113 |  | 
|---|
| 1114 | }  // end cmd_trace | 
|---|
| 1115 |  | 
|---|
| 1116 | /////////////////////////////////////////////// | 
|---|
| 1117 | static void cmd_untrace( int argc , char **argv ) | 
|---|
| 1118 | { | 
|---|
| 1119 |     unsigned int cxy; | 
|---|
| 1120 |     unsigned int lid; | 
|---|
| 1121 |  | 
|---|
| 1122 |         if (argc != 3) | 
|---|
| 1123 |     { | 
|---|
| 1124 |                 printf("  usage: untrace cxy lid \n"); | 
|---|
| 1125 |         } | 
|---|
| 1126 |     else | 
|---|
| 1127 |     { | 
|---|
| 1128 |         cxy = atoi(argv[1]); | 
|---|
| 1129 |         lid = atoi(argv[2]); | 
|---|
| 1130 |  | 
|---|
| 1131 |         if( trace( 0 , cxy , lid ) ) | 
|---|
| 1132 |         { | 
|---|
| 1133 |             printf("  error: core[%x,%d] not found\n", cxy, lid ); | 
|---|
| 1134 |         } | 
|---|
| 1135 |     } | 
|---|
| 1136 |  | 
|---|
| 1137 |     // release semaphore to get next command | 
|---|
| 1138 |     sem_post( &semaphore ); | 
|---|
| 1139 |  | 
|---|
| 1140 | }  // end cmd_untrace() | 
|---|
| 1141 |  | 
|---|
| 1142 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 1143 | // Array of commands | 
|---|
| 1144 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 1145 |  | 
|---|
| 1146 | ksh_cmd_t command[] = | 
|---|
| 1147 | { | 
|---|
| 1148 |         { "cat",     "display file content",                            cmd_cat     }, | 
|---|
| 1149 |         { "cd",      "change current directory",                        cmd_cd      }, | 
|---|
| 1150 |         { "cp",      "replicate a file in file system",                 cmd_cp      }, | 
|---|
| 1151 |     { "fg",      "put a process in foreground",                     cmd_fg      }, | 
|---|
| 1152 |     { "display", "display vmm/sched/process/vfs/chdev/txt",         cmd_display }, | 
|---|
| 1153 |         { "load",    "load an user application",                        cmd_load    }, | 
|---|
| 1154 |         { "help",    "list available commands",                         cmd_help    }, | 
|---|
| 1155 |         { "kill",    "kill a process (all threads)",                    cmd_kill    }, | 
|---|
| 1156 |         { "log",     "list registered commands",                        cmd_log     }, | 
|---|
| 1157 |         { "ls",      "list directory entries",                          cmd_ls      }, | 
|---|
| 1158 |         { "mkdir",   "create a new directory",                          cmd_mkdir   }, | 
|---|
| 1159 |         { "mv",      "move a file in file system",                      cmd_mv      }, | 
|---|
| 1160 |         { "pwd",     "print current working directory",                 cmd_pwd     }, | 
|---|
| 1161 |         { "ps",      "display all processes",                           cmd_ps      }, | 
|---|
| 1162 |         { "rm",      "remove a file from file system",                  cmd_rm      }, | 
|---|
| 1163 |         { "rmdir",   "remove a directory from file system",             cmd_rmdir   }, | 
|---|
| 1164 |         { "stat",    "print infos on a given file",                     cmd_stat    }, | 
|---|
| 1165 |         { "trace",   "activate trace for a given core",                 cmd_trace   }, | 
|---|
| 1166 |         { "untrace", "desactivate trace for a given core",              cmd_untrace }, | 
|---|
| 1167 |         { NULL,      NULL,                                                                              NULL        } | 
|---|
| 1168 | }; | 
|---|
| 1169 |  | 
|---|
| 1170 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 1171 | // This function analyses one command (with arguments), executes it, and returns. | 
|---|
| 1172 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 1173 | static void __attribute__ ((noinline)) execute( char * buf ) | 
|---|
| 1174 | { | 
|---|
| 1175 |         int    argc = 0; | 
|---|
| 1176 |         char * argv[MAX_ARGS]; | 
|---|
| 1177 |         int    i; | 
|---|
| 1178 |         int    len = strlen(buf); | 
|---|
| 1179 |  | 
|---|
| 1180 | #if DEBUG_EXECUTE | 
|---|
| 1181 | snprintf( string , 128 , "[ksh] enter %s for command <%s>" , __FUNCTION__ , buf ); | 
|---|
| 1182 | display_string( string ); | 
|---|
| 1183 | #endif | 
|---|
| 1184 |  | 
|---|
| 1185 |         // build argc/argv | 
|---|
| 1186 |         for (i = 0; i < len; i++)  | 
|---|
| 1187 |     { | 
|---|
| 1188 |         // convert SPACE to NUL | 
|---|
| 1189 |                 if (buf[i] == ' ')  | 
|---|
| 1190 |         { | 
|---|
| 1191 |                         buf[i] = '\0'; | 
|---|
| 1192 |                 } | 
|---|
| 1193 |         else if (i == 0 || buf[i - 1] == '\0')  | 
|---|
| 1194 |         { | 
|---|
| 1195 |                         if (argc < MAX_ARGS)  | 
|---|
| 1196 |             { | 
|---|
| 1197 |                                 argv[argc] = &buf[i]; | 
|---|
| 1198 |                                 argc++; | 
|---|
| 1199 |                         } | 
|---|
| 1200 |                 } | 
|---|
| 1201 |         } | 
|---|
| 1202 |  | 
|---|
| 1203 |     // check command | 
|---|
| 1204 |         if (argc == 0) | 
|---|
| 1205 |     { | 
|---|
| 1206 |         // release semaphore to get next command | 
|---|
| 1207 |         sem_post( &semaphore ); | 
|---|
| 1208 |     } | 
|---|
| 1209 |  | 
|---|
| 1210 | #if DEBUG_EXECUTE | 
|---|
| 1211 | snprintf( string , 128 , "\n[ksh] in %s : argc = %d / arg0 = %s / arg1 = %s", | 
|---|
| 1212 | __FUNCTION__ , argc , argv[0], argv[1] ); | 
|---|
| 1213 | #endif | 
|---|
| 1214 |  | 
|---|
| 1215 |     // scan the list of commands to match typed command | 
|---|
| 1216 |     int found = 0; | 
|---|
| 1217 |     for ( i = 0 ; (command[i].name != NULL) && (found == 0) ; i++ ) | 
|---|
| 1218 |     { | 
|---|
| 1219 |         if (strcmp(argv[0], command[i].name) == 0) | 
|---|
| 1220 |         { | 
|---|
| 1221 |                         command[i].fn(argc, argv); | 
|---|
| 1222 |                         found = 1; | 
|---|
| 1223 |                 } | 
|---|
| 1224 |     } | 
|---|
| 1225 |  | 
|---|
| 1226 |     // check undefined command  | 
|---|
| 1227 |         if (!found)  | 
|---|
| 1228 |     {    | 
|---|
| 1229 |         printf("  error : undefined command <%s>\n", argv[0]); | 
|---|
| 1230 |  | 
|---|
| 1231 |         // release semaphore to get next command | 
|---|
| 1232 |         sem_post( &semaphore ); | 
|---|
| 1233 |         } | 
|---|
| 1234 | }  // end execute() | 
|---|
| 1235 |  | 
|---|
| 1236 |  | 
|---|
| 1237 |  | 
|---|
| 1238 | /////////////////////////////// | 
|---|
| 1239 | static void interactive( void ) | 
|---|
| 1240 | { | 
|---|
| 1241 |         char           c;                                               // read character | 
|---|
| 1242 |     unsigned int   end_command;             // last character found in a command | 
|---|
| 1243 |         unsigned int   count;                   // pointer in command buffer | 
|---|
| 1244 |         unsigned int   i;                                               // index for loops | 
|---|
| 1245 |         unsigned int   state;                   // escape sequence state | 
|---|
| 1246 |  | 
|---|
| 1247 |         char           cmd[CMD_MAX_SIZE];               // buffer for one command | 
|---|
| 1248 |  | 
|---|
| 1249 | /*  direct command to help debug | 
|---|
| 1250 |  | 
|---|
| 1251 |     int pid = getpid(); | 
|---|
| 1252 |  | 
|---|
| 1253 |     if( pid == 3 ) | 
|---|
| 1254 |     { | 
|---|
| 1255 |         if( sem_wait( &semaphore ) ) | 
|---|
| 1256 |         { | 
|---|
| 1257 |             printf("\n[ksh %d] error : cannot found semafore\n" ); | 
|---|
| 1258 |             exit( 1 ); | 
|---|
| 1259 |         } | 
|---|
| 1260 |         else | 
|---|
| 1261 |         { | 
|---|
| 1262 |             strcpy( cmd , "load bin/user/tcp_server.elf" ); | 
|---|
| 1263 |             printf("[ksh] %s\n", cmd ); | 
|---|
| 1264 |             execute( cmd ); | 
|---|
| 1265 |         } | 
|---|
| 1266 |     } | 
|---|
| 1267 |     else if( getpid() == 4 ) | 
|---|
| 1268 |     { | 
|---|
| 1269 |         if( sem_wait( &semaphore ) ) | 
|---|
| 1270 |         { | 
|---|
| 1271 |             printf("\n[ksh %d] error : cannot found semafore\n" ); | 
|---|
| 1272 |             exit( 1 ); | 
|---|
| 1273 |         } | 
|---|
| 1274 |         else | 
|---|
| 1275 |         { | 
|---|
| 1276 |             strcpy( cmd , "load bin/user/tcp_client.elf" ); | 
|---|
| 1277 |             printf("[ksh] %s\n", cmd ); | 
|---|
| 1278 |             execute( cmd ); | 
|---|
| 1279 |         } | 
|---|
| 1280 |     } | 
|---|
| 1281 |  | 
|---|
| 1282 | */ | 
|---|
| 1283 |  | 
|---|
| 1284 |  | 
|---|
| 1285 |         enum fsm_states  | 
|---|
| 1286 |     { | 
|---|
| 1287 |                 NORMAL = 0, | 
|---|
| 1288 |                 ESCAPE = 1, | 
|---|
| 1289 |                 BRAKET = 2, | 
|---|
| 1290 |         }; | 
|---|
| 1291 |  | 
|---|
| 1292 |         // This lexical analyser writes one command line in the command buffer. | 
|---|
| 1293 |         // It is implemented as a 3 states FSM to handle the following escape sequences: | 
|---|
| 1294 |         // - ESC [ A : up arrow | 
|---|
| 1295 |         // - ESC [ B : down arrow | 
|---|
| 1296 |         // - ESC [ C : right arrow | 
|---|
| 1297 |         // - ESC [ D : left arrow | 
|---|
| 1298 |         // The three states have the following semantic: | 
|---|
| 1299 |         // - NORMAL : no (ESC) character has been found | 
|---|
| 1300 |         // - ESCAPE : the character (ESC) has been found | 
|---|
| 1301 |         // - BRAKET : the wo characters (ESC,[) have been found | 
|---|
| 1302 |  | 
|---|
| 1303 |     // take the semaphore for the first command | 
|---|
| 1304 |     if ( sem_wait( &semaphore ) ) | 
|---|
| 1305 |     { | 
|---|
| 1306 |         printf("\n[ksh error] cannot found semafore\n" ); | 
|---|
| 1307 |         exit( 1 ); | 
|---|
| 1308 |     } | 
|---|
| 1309 |  | 
|---|
| 1310 |     // display prompt for the first command | 
|---|
| 1311 |     printf("\n[ksh] "); | 
|---|
| 1312 |  | 
|---|
| 1313 |     // external loop on the commands / the interactive thread do not exit this loop | 
|---|
| 1314 |         while (1) | 
|---|
| 1315 |         { | 
|---|
| 1316 |             // initialize command buffer | 
|---|
| 1317 |             count       = 0; | 
|---|
| 1318 |             state       = NORMAL; | 
|---|
| 1319 |         end_command = 0; | 
|---|
| 1320 |  | 
|---|
| 1321 | #if DEBUG_INTER  | 
|---|
| 1322 | snprintf( string , 128 , "[ksh] %s : request a new command", __FUNCTION__ ); | 
|---|
| 1323 | display_string( string ); | 
|---|
| 1324 | #endif | 
|---|
| 1325 |  | 
|---|
| 1326 |         // internal loop on characters in one command | 
|---|
| 1327 |         while( end_command == 0 ) | 
|---|
| 1328 |         { | 
|---|
| 1329 |             // get one character from TXT_RX | 
|---|
| 1330 |                 c = (char)getchar(); | 
|---|
| 1331 |  | 
|---|
| 1332 |             if( c == 0 ) continue; | 
|---|
| 1333 |  | 
|---|
| 1334 |                     if( state == NORMAL )  // we are not in an escape sequence | 
|---|
| 1335 |                     { | 
|---|
| 1336 |                                 if ((c == '\b') || (c == 0x7F))  // backspace => remove one character | 
|---|
| 1337 |                                 { | 
|---|
| 1338 |                                     if (count > 0) | 
|---|
| 1339 |                     { | 
|---|
| 1340 |                                         printf("\b \b"); | 
|---|
| 1341 |                                         count--; | 
|---|
| 1342 |                                     } | 
|---|
| 1343 |                                 } | 
|---|
| 1344 |                                 else if (c == '\n')                  // new line => end of command | 
|---|
| 1345 |                                 { | 
|---|
| 1346 |                                     if (count > 0)               // analyse & execute command | 
|---|
| 1347 |                                     { | 
|---|
| 1348 |                                             // complete command with NUL character | 
|---|
| 1349 |                                             cmd[count] = 0; | 
|---|
| 1350 |                         count++; | 
|---|
| 1351 | #if DEBUG_INTER | 
|---|
| 1352 | snprintf( string , 128 , "[ksh] %s : get command <%s>", __FUNCTION__, cmd ); | 
|---|
| 1353 | display_string( string ); | 
|---|
| 1354 | #endif | 
|---|
| 1355 |                         // register command in log_entries[] array | 
|---|
| 1356 |                                             strncpy( log_entries[ptw].buf , cmd , count ); | 
|---|
| 1357 |                                             log_entries[ptw].count = count; | 
|---|
| 1358 |                                             ptw = (ptw + 1) % LOG_DEPTH; | 
|---|
| 1359 |                                             ptr = ptw; | 
|---|
| 1360 |  | 
|---|
| 1361 | #if DEBUG_INTER | 
|---|
| 1362 | snprintf( string , 128 , "[ksh] %s : execute <%s>", __FUNCTION__, cmd ); | 
|---|
| 1363 | display_string( string ); | 
|---|
| 1364 | #endif | 
|---|
| 1365 |                         // echo character | 
|---|
| 1366 |                         putchar( c ); | 
|---|
| 1367 |  | 
|---|
| 1368 |                                             // execute command | 
|---|
| 1369 |                                             execute( cmd ); | 
|---|
| 1370 |                                     } | 
|---|
| 1371 |                     else                         // no command registered | 
|---|
| 1372 |                     { | 
|---|
| 1373 |                         // release semaphore to get next command | 
|---|
| 1374 |                         sem_post( &semaphore ); | 
|---|
| 1375 |                     } | 
|---|
| 1376 |  | 
|---|
| 1377 |                     // exit internal loop on characters | 
|---|
| 1378 |                     end_command = 1; | 
|---|
| 1379 |                 } | 
|---|
| 1380 |                             else if (c == '\t')             // tabulation => do nothing | 
|---|
| 1381 |                                 { | 
|---|
| 1382 |                             } | 
|---|
| 1383 |                             else if (c == (char)0x1B)       // ESC => start an escape sequence | 
|---|
| 1384 |                             { | 
|---|
| 1385 |                     state = ESCAPE; | 
|---|
| 1386 |                             } | 
|---|
| 1387 |                             else                                               // normal character | 
|---|
| 1388 |                                 { | 
|---|
| 1389 |                                     if (count < (sizeof(cmd) - 1) ) | 
|---|
| 1390 |                                     { | 
|---|
| 1391 |                         // register character in command buffer | 
|---|
| 1392 |                                             cmd[count] = c; | 
|---|
| 1393 |                                             count++; | 
|---|
| 1394 |  | 
|---|
| 1395 |                         // echo character | 
|---|
| 1396 |                         putchar( c ); | 
|---|
| 1397 |                                         } | 
|---|
| 1398 |                     else | 
|---|
| 1399 |                     { | 
|---|
| 1400 |                                 printf("\none command cannot exceed %d characters\n", sizeof(cmd) ); | 
|---|
| 1401 |                     } | 
|---|
| 1402 |                                 } | 
|---|
| 1403 |                         } | 
|---|
| 1404 |                         else if( state == ESCAPE )   | 
|---|
| 1405 |                         { | 
|---|
| 1406 |                                 if (c == '[')           //  valid sequence => continue | 
|---|
| 1407 |                                 { | 
|---|
| 1408 |                                         state = BRAKET; | 
|---|
| 1409 |                                 } | 
|---|
| 1410 |                                 else                               // invalid sequence => do nothing | 
|---|
| 1411 |                                 { | 
|---|
| 1412 |                                         state = NORMAL; | 
|---|
| 1413 |                                 } | 
|---|
| 1414 |                         } | 
|---|
| 1415 |                         else if( state == BRAKET ) | 
|---|
| 1416 |                         { | 
|---|
| 1417 |                                 if (c == 'D')   // valid  LEFT sequence => move cmd pointer left | 
|---|
| 1418 |                                 { | 
|---|
| 1419 |                                         if (count > 0) | 
|---|
| 1420 |                                         { | 
|---|
| 1421 |                                                 printf("\b"); | 
|---|
| 1422 |                                                 count--; | 
|---|
| 1423 |                                         } | 
|---|
| 1424 |  | 
|---|
| 1425 |                                         // get next user char | 
|---|
| 1426 |                                         state = NORMAL; | 
|---|
| 1427 |                                 } | 
|---|
| 1428 |                                 else if (c == 'C')   // valid  RIGHT sequence => move cmd pointer right | 
|---|
| 1429 |                                 { | 
|---|
| 1430 |                                         if (count < sizeof(cmd) - 1) | 
|---|
| 1431 |                                         { | 
|---|
| 1432 |                                                 printf("%c", cmd[count]); | 
|---|
| 1433 |                                                 count++; | 
|---|
| 1434 |                                         } | 
|---|
| 1435 |  | 
|---|
| 1436 |                                         // get next user char | 
|---|
| 1437 |                                         state = NORMAL; | 
|---|
| 1438 |                                 } | 
|---|
| 1439 |                                 else if (c == 'A')   // valid  UP sequence => move log pointer backward | 
|---|
| 1440 |                                 { | 
|---|
| 1441 |                                         // cancel current command | 
|---|
| 1442 |                                         for (i = 0; i < count; i++) printf("\b \b"); | 
|---|
| 1443 |                                         count = 0; | 
|---|
| 1444 |  | 
|---|
| 1445 |                                         // copy log command into cmd | 
|---|
| 1446 |                                         ptr = (ptr - 1) % LOG_DEPTH; | 
|---|
| 1447 |                                         strcpy(cmd, log_entries[ptr].buf); | 
|---|
| 1448 |                                         count = log_entries[ptr].count - 1; | 
|---|
| 1449 |  | 
|---|
| 1450 |                                         // display log command | 
|---|
| 1451 |                                         printf("%s", cmd); | 
|---|
| 1452 |  | 
|---|
| 1453 |                                         // get next user char | 
|---|
| 1454 |                                         state = NORMAL; | 
|---|
| 1455 |                                 } | 
|---|
| 1456 |                                 else if (c == 'B')   // valid  DOWN sequence => move log pointer forward | 
|---|
| 1457 |                                 { | 
|---|
| 1458 |                                         // cancel current command | 
|---|
| 1459 |                                         for (i = 0 ; i < count; i++) printf("\b \b"); | 
|---|
| 1460 |                                         count = 0; | 
|---|
| 1461 |  | 
|---|
| 1462 |                                         // copy log command into cmd | 
|---|
| 1463 |                                         ptr = (ptr + 1) % LOG_DEPTH; | 
|---|
| 1464 |                                         strcpy(cmd, log_entries[ptr].buf); | 
|---|
| 1465 |                                         count = log_entries[ptr].count; | 
|---|
| 1466 |  | 
|---|
| 1467 |                                         // display log command | 
|---|
| 1468 |                                         printf("%s", cmd); | 
|---|
| 1469 |  | 
|---|
| 1470 |                                         // get next user char | 
|---|
| 1471 |                                         state = NORMAL; | 
|---|
| 1472 |                                 } | 
|---|
| 1473 |                                 else                               // other character => do nothing | 
|---|
| 1474 |                                 { | 
|---|
| 1475 |                                         // get next user char | 
|---|
| 1476 |                                         state = NORMAL; | 
|---|
| 1477 |                                 } | 
|---|
| 1478 |                         } | 
|---|
| 1479 |                 }  // end internal while loop on characters | 
|---|
| 1480 |  | 
|---|
| 1481 | #if DEBUG_INTER  | 
|---|
| 1482 | snprintf( string , 128 , "\n[ksh] %s : complete <%s> command", __FUNCTION__, cmd ); | 
|---|
| 1483 | display_string( string ); | 
|---|
| 1484 | #endif | 
|---|
| 1485 |  | 
|---|
| 1486 |         // block interactive thread if KSH loose TXT ownership | 
|---|
| 1487 |         if ( sem_wait( &semaphore ) ) | 
|---|
| 1488 |         { | 
|---|
| 1489 |             printf("\n[ksh error] cannot found semafore\n" ); | 
|---|
| 1490 |             exit( 1 ); | 
|---|
| 1491 |         } | 
|---|
| 1492 |  | 
|---|
| 1493 |         // display prompt for next command | 
|---|
| 1494 |         printf("\n[ksh] "); | 
|---|
| 1495 |  | 
|---|
| 1496 |         }  // end external while loop on commands | 
|---|
| 1497 |  | 
|---|
| 1498 | }  // end interactive() | 
|---|
| 1499 |  | 
|---|
| 1500 | //////////////// | 
|---|
| 1501 | int main( void ) | 
|---|
| 1502 | { | 
|---|
| 1503 |     unsigned int cxy;             // owner cluster identifier for this KSH process | 
|---|
| 1504 |     unsigned int lid;             // core identifier for this KSH main thread | 
|---|
| 1505 |     int          status;          // child process termination status | 
|---|
| 1506 |     int          parent_pid;      // parent process identifier (i.e. this process) | 
|---|
| 1507 |     int          child_pid;       // child process identifier | 
|---|
| 1508 |     unsigned int is_owner;        // non-zero if KSH process is TXT owner | 
|---|
| 1509 |  | 
|---|
| 1510 |     // initialize log buffer | 
|---|
| 1511 |         memset( &log_entries , 0, sizeof(log_entries)); | 
|---|
| 1512 |         ptw   = 0; | 
|---|
| 1513 |         ptr   = 0; | 
|---|
| 1514 |  | 
|---|
| 1515 |     // get KSH process pid and core | 
|---|
| 1516 |     parent_pid = getpid(); | 
|---|
| 1517 |     get_core_id( &cxy , &lid ); | 
|---|
| 1518 |  | 
|---|
| 1519 | #if DEBUG_MAIN | 
|---|
| 1520 | snprintf( string , 128 , "\n[ksh] main thread started on core[%x,%d]", cxy , lid );  | 
|---|
| 1521 | display_string( string ); | 
|---|
| 1522 | #endif | 
|---|
| 1523 |      | 
|---|
| 1524 |     // initializes the semaphore used to synchronize with interactive thread | 
|---|
| 1525 |     if ( sem_init( &semaphore , 0 , 1 ) ) | 
|---|
| 1526 |     { | 
|---|
| 1527 |         printf("\n[KSH ERROR] cannot initialize semaphore\n" ); | 
|---|
| 1528 |         exit( 1 );  | 
|---|
| 1529 |     } | 
|---|
| 1530 |  | 
|---|
| 1531 | #if DEBUG_MAIN | 
|---|
| 1532 | snprintf( string , 128 , "\n[ksh] main initialized semaphore" );  | 
|---|
| 1533 | display_string( string ); | 
|---|
| 1534 | #endif | 
|---|
| 1535 |      | 
|---|
| 1536 |     // initialize interactive thread attributes | 
|---|
| 1537 |     attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED; | 
|---|
| 1538 |     attr.cxy        = cxy; | 
|---|
| 1539 |  | 
|---|
| 1540 |     // lauch the interactive thread  | 
|---|
| 1541 |     pthread_create( &trdid, | 
|---|
| 1542 |                     &attr, | 
|---|
| 1543 |                     &interactive,   // entry function | 
|---|
| 1544 |                     NULL );  | 
|---|
| 1545 | #if DEBUG_MAIN | 
|---|
| 1546 | snprintf( string , 128 , "\n[ksh] main thread launched interactive thread %x", trdid );  | 
|---|
| 1547 | display_string( string ); | 
|---|
| 1548 | #endif | 
|---|
| 1549 |  | 
|---|
| 1550 |     // signal INIT process | 
|---|
| 1551 |     kill( 1 , SIGCONT ); | 
|---|
| 1552 |      | 
|---|
| 1553 |     // enter infinite loop monitoring children processes termination  | 
|---|
| 1554 |     while( 1 ) | 
|---|
| 1555 |     { | 
|---|
| 1556 |         // wait children termination | 
|---|
| 1557 |         child_pid = wait( &status ); | 
|---|
| 1558 |  | 
|---|
| 1559 |         if( DEBUG_MAIN ) | 
|---|
| 1560 |         { | 
|---|
| 1561 |             if(WIFEXITED  (status)) printf("\n[ksh] child process %x exit\n"   ,child_pid); | 
|---|
| 1562 |             if(WIFSIGNALED(status)) printf("\n[ksh] child process %x killed\n" ,child_pid); | 
|---|
| 1563 |             if(WIFSTOPPED (status)) printf("\n[ksh] child process %x stopped\n",child_pid); | 
|---|
| 1564 |         } | 
|---|
| 1565 |  | 
|---|
| 1566 |         // release semaphore if KSH process is TXT owner, to unblock interactive thread | 
|---|
| 1567 |         is_fg( parent_pid , &is_owner ); | 
|---|
| 1568 |         if( is_owner ) sem_post( &semaphore ); | 
|---|
| 1569 |     } | 
|---|
| 1570 | }  // end main() | 
|---|
| 1571 |  | 
|---|
| 1572 |  | 
|---|