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

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

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

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