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

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

euh...

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