source: trunk/user/ksh/ksh.c @ 678

Last change on this file since 678 was 676, checked in by alain, 4 years ago

Introduce chat application to test the named pipes.

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