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