source: soft/giet_vm/applications/shell/shell.c @ 783

Last change on this file since 783 was 782, checked in by alain, 9 years ago

1) Introduce the string library.
2) Introduce a heap in the shell application.

File size: 16.1 KB
RevLine 
[589]1///////////////////////////////////////////////////////////////////////////////////////
[782]2// File    : shell.c   
3// Date    : july 2015
4// authors : Clément Guérin and Alain Greiner
[589]5///////////////////////////////////////////////////////////////////////////////////////
[782]6// Simple shell for the GIET_VM.
[589]7///////////////////////////////////////////////////////////////////////////////////////
8
9#include "stdio.h"
[703]10#include "stdlib.h"
[589]11#include "malloc.h"
[782]12#include "string.h"
[589]13
[747]14#define BUF_SIZE    (256)        // buffer for one command
15#define MAX_ARGS    (32)         // max number of arguments in a command
[782]16#define FIFO_SIZE   (1024)       // FIFO depth for recursive ls
[589]17
[712]18
[640]19struct command_t
20{
21    char *name;
[708]22    char *desc;
[640]23    void (*fn)(int, char**);
24};
[589]25
[640]26////////////////////////////////////////////////////////////////////////////////
[643]27//  Shell  Commands
28////////////////////////////////////////////////////////////////////////////////
[640]29
30struct command_t cmd[];
31
[643]32///////////////////////////////////////////
[640]33static void cmd_help(int argc, char** argv)
[589]34{
[640]35    int i;
[589]36
[640]37    giet_tty_printf("available commands:\n");
[610]38
[640]39    for (i = 0; cmd[i].name; i++)
[589]40    {
[708]41        giet_tty_printf("\t%s\t : %s\n", cmd[i].name , cmd[i].desc );
[589]42    }
[640]43}
44
[708]45///////////////////////////////////////////
46static void cmd_time(int argc, char** argv)
[640]47{
[775]48    giet_tty_printf(" cycle = %d\n", giet_proctime());
[640]49}
50
[782]51
[643]52/////////////////////////////////////////
[640]53static void cmd_ls(int argc, char** argv)
54{
[782]55    fat_dirent_t    entry;
56    unsigned int    recursive;
57    char*           paths[FIFO_SIZE];
58    unsigned int    ptr = 0;
59    unsigned int    ptw = 0;
[660]60
[782]61    // analyse arguments
[775]62    if (argc == 2)
[708]63    {
[782]64        // allocate a buffer for root directory
65        // pathname, and push it in FIFO
66        paths[ptw] = malloc( strlen(argv[1]) );
67        strcpy( paths[ptw] , argv[1] );
68
69giet_tty_printf("\n@@@ arg = %s / path = %s\n", argv[1] , paths[ptw] );
70
71        ptw = (ptw + 1) % FIFO_SIZE;
72
73        // not recursive
74        recursive = 0;
[775]75    }
76    else if ( (argc == 3) && (strcmp( argv[1] , "-r" ) == 0) )
77    {
[782]78        // allocate a buffer for root directory
79        // pathname, and push it in FIFO
80        paths[ptw] = malloc( strlen(argv[2]) );
81        strcpy( paths[ptw] , argv[2] );
82        ptw = (ptw + 1) % FIFO_SIZE;
[775]83
[782]84        // recursive
85        recursive = 1;
[708]86    }
[775]87    else
88    {
89        giet_tty_printf("  usage : ls [-r] pathname\n");
90        return;
91    }
[660]92
[782]93    // loop on registered directories
94    do
[589]95    {
[782]96        // open directory
97        int fd  = giet_fat_opendir( paths[ptr] );
98        if (fd < 0)
99        {
100            giet_tty_printf("  error : cannot open %s\n", paths[ptr] );
101            return;
102        }
[589]103
[782]104        // display directory pathname
105        giet_tty_printf("*** %s ***\n", paths[ptr] );
[660]106
[782]107        // loop on directory entries
108        while (giet_fat_readdir(fd, &entry) == 0)
109        {
110            // display entry
111            if ( entry.is_dir ) giet_tty_printf("dir ");
112            else                giet_tty_printf("file");
113            giet_tty_printf(" | size = %d \t| cluster = %x \t| %s\n",
114                            entry.size, entry.cluster, entry.name );
[660]115
[782]116            // allocate a buffer for subdirectory pathname
117            // and push it in FIFO if required
118            if ( entry.is_dir && recursive && 
119                 ( strcmp( entry.name , "." ) != 0 ) && 
120                 ( strcmp( entry.name , ".." ) != 0 ) )
121            {
122                // check FIFO full
123                if ( ((ptr - ptw) % FIFO_SIZE) == 1 )
124                {
125                    giet_tty_printf("   sorry, not enough memory for recursive ls\n");
126                    return;
127                }
[640]128
[782]129                unsigned int length = strlen(paths[ptr]) + strlen(entry.name) + 2;
130                paths[ptw] = malloc( length );
131                if ( strcmp( paths[ptr] , "/" ) == 0 )
132                {
133                    snprintf( paths[ptw] , length , "/%s" , entry.name );
134                }
135                else
136                {
137                    snprintf( paths[ptw] , length , "%s/%s" , paths[ptr] , entry.name );
138                }
139                ptw = (ptw + 1) % FIFO_SIZE;   
140            }
141        }  // end loop on entries
142
143        // close directory
144        giet_fat_closedir(fd);
145
146        // release the directory pathname buffer
147        // and pop it from FIFO
148        free( paths[ptr] );
149        ptr = (ptr + 1) % FIFO_SIZE;
150
151    } while ( ptr != ptw );
152
153}  // end cmd_ls()
154
[643]155////////////////////////////////////////////
[640]156static void cmd_mkdir(int argc, char** argv)
157{
158    if (argc < 2)
[589]159    {
[775]160        giet_tty_printf("  usage : mkdir pathname\n");
[640]161        return;
[589]162    }
[640]163
164    int ret = giet_fat_mkdir(argv[1]);
[708]165
[640]166    if (ret < 0)
[589]167    {
[708]168        giet_tty_printf("  error : cannot create directory %s / err = %d\n", argv[1], ret);
[589]169    }
[640]170}
[589]171
[643]172/////////////////////////////////////////
[640]173static void cmd_cp(int argc, char** argv)
174{
175    if (argc < 3)
[589]176    {
[775]177        giet_tty_printf("  usage : cp src_pathname dst_pathname>\n");
[640]178        return;
[589]179    }
180
[640]181    char buf[1024];
182    int src_fd = -1;
183    int dst_fd = -1;
[660]184    fat_file_info_t info;
[640]185    int size;
186    int i;
187
188    src_fd = giet_fat_open( argv[1] , O_RDONLY );
189    if (src_fd < 0)
[589]190    {
[708]191        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[1], src_fd);
[640]192        goto exit;
[589]193    }
[640]194
195    giet_fat_file_info(src_fd, &info);
[708]196
[640]197    if (info.is_dir)
[589]198    {
[708]199        giet_tty_printf("  error : %s is a directory\n", argv[1] );
[640]200        goto exit;
[589]201    }
[708]202
[640]203    size = info.size;
[589]204
[772]205    dst_fd = giet_fat_open( argv[2] , O_CREAT | O_TRUNC);
[708]206
[640]207    if (dst_fd < 0)
[589]208    {
[708]209        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[2], dst_fd);
[640]210        goto exit;
[589]211    }
212
[640]213    giet_fat_file_info(dst_fd, &info);
[708]214
[640]215    if (info.is_dir)
[589]216    {
[775]217        giet_tty_printf("  error : %s is a directory\n", argv[2] );  // TODO
[640]218        goto exit;
[589]219    }
[640]220
221    i = 0;
222    while (i < size)
[589]223    {
[640]224        int len = (size - i < 1024 ? size - i : 1024);
225        int wlen;
226
227        len = giet_fat_read(src_fd, &buf, len);
228        wlen = giet_fat_write(dst_fd, &buf, len);
229        if (wlen != len)
230        {
[708]231            giet_tty_printf("  error : cannot write on device\n");
[640]232            goto exit;
233        }
234        i += len;
[589]235    }
236
[640]237exit:
238    if (src_fd >= 0)
239        giet_fat_close(src_fd);
240    if (dst_fd >= 0)
241        giet_fat_close(dst_fd);
242}
243
[669]244/////////////////////////////////////////
[640]245static void cmd_rm(int argc, char **argv)
246{
247    if (argc < 2)
[589]248    {
[775]249        giet_tty_printf("  usage : rm pathname\n");
[640]250        return;
[589]251    }
[640]252
253    int ret = giet_fat_remove(argv[1], 0);
[708]254
[640]255    if (ret < 0)
[589]256    {
[708]257        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
[589]258    }
[640]259}
[589]260
[643]261////////////////////////////////////////////
[640]262static void cmd_rmdir(int argc, char **argv)
263{
264    if (argc < 2)
[589]265    {
[775]266        giet_tty_printf("  usage : rmdir pathname\n");
[640]267        return;
[589]268    }
[640]269
270    int ret = giet_fat_remove(argv[1], 1);
271    if (ret < 0)
[589]272    {
[708]273        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
[589]274    }
[640]275}
[589]276
[643]277/////////////////////////////////////////
[640]278static void cmd_mv(int argc, char **argv)
279{
280    if (argc < 3)
[589]281    {
[775]282        giet_tty_printf("  usage : %s src_pathname dst_pathname\n", argv[0]);
[640]283        return;
[589]284    }
[640]285
286    int ret = giet_fat_rename(argv[1], argv[2]);
287    if (ret < 0)
[589]288    {
[708]289        giet_tty_printf("error : cannot move %s to %s / err = %d\n", argv[1], argv[2], ret );
[589]290    }
[640]291}
[589]292
[643]293///////////////////////////////////////////
294static void cmd_exec(int argc, char **argv)
295{
296    if (argc < 2)
297    {
[775]298        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
[643]299        return;
300    }
301
302    int ret = giet_exec_application(argv[1]);
303    if ( ret == -1 )
304    {
[708]305        giet_tty_printf("  error : %s not found\n", argv[1] );
[643]306    }
307}
308
309///////////////////////////////////////////
310static void cmd_kill(int argc, char **argv)
311{
312    if (argc < 2)
313    {
[775]314        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
[643]315        return;
316    }
317
318    int ret = giet_kill_application(argv[1]);
319    if ( ret == -1 )
320    {
[708]321        giet_tty_printf("  error : %s not found\n", argv[1] );
[643]322    }
323    if ( ret == -2 )
324    {
[708]325        giet_tty_printf("  error : %s cannot be killed\n", argv[1] );
[643]326    }
327}
328
[708]329/////////////////////////////////////////
[687]330static void cmd_ps(int argc, char** argv)
331{
[712]332    if (argc == 1)
333    {
334        giet_applications_status( NULL );
335    }
336    else
337    {
338        giet_applications_status( argv[1] );
339    }
[687]340}
341
[708]342////////////////////////////////////////////
343static void cmd_pause(int argc, char** argv)
[703]344{
[708]345    if (argc < 3)
346    {
[775]347        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
[708]348        return;
349    }
[703]350
[712]351    giet_pthread_control( THREAD_CMD_PAUSE , argv[1] , argv[2] );
[708]352}
353
354/////////////////////////////////////////////
355static void cmd_resume(int argc, char** argv)
356{
357    if (argc < 3)
358    {
[775]359        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
[703]360        return;
361    }
362
[712]363    giet_pthread_control( THREAD_CMD_RESUME , argv[1] , argv[2] );
[703]364}
365
[708]366/////////////////////////////////////////////
367static void cmd_context(int argc, char** argv)
368{
369    if (argc < 3)
370    {
[775]371        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
[708]372        return;
373    }
374
[712]375    giet_pthread_control( THREAD_CMD_CONTEXT , argv[1] , argv[2] );
[708]376}
377
[747]378/////////////////////////////////////////////
379static void cmd_cat(int argc, char** argv)
380{
[775]381    if (argc != 2)
[747]382    {
[775]383        giet_tty_printf("  usage : cat pathname \n");
[747]384        return;
385    }
[708]386
[768]387    unsigned int     x,y,p;          // processor coordinates
[747]388    unsigned int     fd;             // file descriptor
389    fat_file_info_t  info;           // file info
390    unsigned int     size;           // buffer size (file_size + 1)
[768]391    unsigned int     bytes;          // number of bytes to be mapped 
392    char*            buf = NULL;     // temporary buffer
[747]393
394    // get processor coordinates
395    giet_proc_xyp( &x , &y , &p );
396   
397    // open the file to display   
[768]398    fd = giet_fat_open( argv[1] , 0 );
[747]399    if (fd < 0)
400    {
401        giet_tty_printf("  error : cannot open %s\n", argv[1]);
402        goto exit;
403    }
404
405    // get file size
406    giet_fat_file_info( fd, &info );
407    if ( info.is_dir )
408    {
409        giet_tty_printf("  error : %s is a directory\n", argv[1] );
410        goto exit;
411    }
412    size = info.size; 
413
[768]414    // extend size to 4 Kbytes boundary if required
415    if ( (size+1) & 0xFFF)  bytes = (size & 0xFFFFF000) + 0x1000;
416    else                    bytes = size + 1;
417
418    // map local buffer to Cache_file
419    buf = giet_fat_mmap( NULL,
420                         bytes,
421                         MAP_PROT_READ | MAP_PROT_WRITE, 
422                         MAP_SHARED,
423                         fd,
424                         0 ); 
425    if ( buf == NULL )
426    {
427        giet_tty_printf("  error : cannot map %s\n", argv[1] );
428        goto exit;
429    }
430
431    // set terminating '0'
[747]432    buf[size] = 0;
433
434    // display the file content
[768]435    giet_tty_printf("%s", buf );
[747]436
437exit:
438    if ( fd >= 0 )     giet_fat_close( fd );
[768]439    if ( buf != NULL ) giet_fat_munmap( buf , bytes );
[747]440}
441
[775]442///////////////////////////////////////////
443static void cmd_dump(int argc, char** argv)
444{
445    if ((argc == 2) && (strcmp( argv[1] , "-bs" ) == 0))
446    {
447        giet_fat_dump( DUMP_BS , NULL , 0 );
448    }
449    else if ((argc == 2) && (strcmp( argv[1] , "-fs" ) == 0))
450    {
451        giet_fat_dump( DUMP_FS , NULL , 0 );
452    }
453    else if ((argc == 3) && (strcmp( argv[1] , "-fat" ) == 0))
454    {
455        giet_fat_dump( DUMP_FAT , NULL , atoi( argv[2] ) );
456    }
457    else if ((argc == 4) && (strcmp( argv[1] , "-file" ) == 0))
458    {
459        giet_fat_dump( DUMP_FILE , argv[2] , atoi( argv[3] ) );
460    }
461    else if ((argc == 4) && (strcmp( argv[1] , "-dir" ) == 0))
462    {
463        giet_fat_dump( DUMP_DIR , argv[2] , atoi( argv[3] ) );
464    }
465    else
466    {
467        giet_tty_printf("  usage : dump [-bs] [-fs] [-fat block] "
468                        "[-file pathname block] [-dir pathname block]\n");
469        return;
470    }
471}
472
473
[643]474////////////////////////////////////////////////////////////////////
[640]475struct command_t cmd[] =
476{
[747]477    { "cat",        "display file content",                 cmd_cat },
478    { "context",    "display a thread context",             cmd_context },
479    { "cp",         "replicate a file in file system",      cmd_cp },
[775]480    { "dump",       "display content of disk sector",       cmd_dump },
[747]481    { "exec",       "start an application",                 cmd_exec },
[708]482    { "help",       "list available commands",              cmd_help },
[747]483    { "kill",       "kill an application (all threads)",    cmd_kill },
[708]484    { "ls",         "list content of a directory",          cmd_ls },
485    { "mkdir",      "create a new directory",               cmd_mkdir },
486    { "mv",         "move a file in file system",           cmd_mv },
[747]487    { "pause",      "pause a thread",                       cmd_pause },
[708]488    { "ps",         "list all mapped applications status",  cmd_ps },
489    { "resume",     "resume a thread",                      cmd_resume },
[747]490    { "rm",         "remove a file from file system",       cmd_rm },
491    { "rmdir",      "remove a directory from file system",  cmd_rmdir },
492    { "time",       "return current date",                  cmd_time },
[708]493    { NULL,         NULL,                                   NULL }
[640]494};
495
[643]496// shell
[640]497
[747]498///////////////////////////////////////////////////////////////////
499// This function analyses one command (with arguments)
500///////////////////////////////////////////////////////////////////
[703]501static void parse(char *buf)
[640]502{
503    int argc = 0;
504    char* argv[MAX_ARGS];
505    int i;
506    int len = strlen(buf);
507
508    // build argc/argv
509    for (i = 0; i < len; i++)
[589]510    {
[640]511        if (buf[i] == ' ')
512        {
513            buf[i] = '\0';
514        }
515        else if (i == 0 || buf[i - 1] == '\0')
516        {
517            if (argc < MAX_ARGS)
518            {
519                argv[argc] = &buf[i];
520                argc++;
521            }
522        }
[589]523    }
[640]524
525    if (argc > 0)
[589]526    {
[640]527        int found = 0;
528
529        // try to match typed command with built-ins
530        for (i = 0; cmd[i].name; i++)
531        {
532            if (strcmp(argv[0], cmd[i].name) == 0)
533            {
534                // invoke
535                cmd[i].fn(argc, argv);
536                found = 1;
537                break;
538            }
539        }
540
541        if (!found)
542        {
[643]543            giet_tty_printf("undefined command %s\n", argv[0]);
[640]544        }
[589]545    }
[640]546}
[589]547
[643]548////////////////////
[640]549static void prompt()
550{
551    giet_tty_printf("# ");
552}
553
554//////////////////////////////////////////
555__attribute__ ((constructor)) void main()
556//////////////////////////////////////////
557{
558    char c;
559    char buf[BUF_SIZE];
560    int count = 0;
561
[669]562    // get a private TTY
563    giet_tty_alloc( 0 );
[708]564    giet_tty_printf( "~~~ shell ~~~\n\n" );
[669]565
[782]566    // heap initialisation
567    unsigned int x_id;                          // x cluster coordinate
568    unsigned int y_id;                          // y cluster coordinate
569    unsigned int p_id;                          // local processor index
570    giet_proc_xyp( &x_id , &y_id , &p_id );
571    heap_init( x_id , y_id );
572
[669]573    // display first prompt
[640]574    prompt();
575
576    while (1)
[589]577    {
[640]578        giet_tty_getc(&c);
579
580        switch (c)
581        {
[747]582        case '\b':                       // backspace
[640]583            if (count > 0)
584            {
585                giet_tty_printf("\b \b");
586                count--;
587            }
588            break;
[747]589        case '\n':                       // new line
[640]590            giet_tty_printf("\n");
591            if (count > 0)
592            {
593                buf[count] = '\0';
[703]594                parse((char*)&buf);
[640]595            }
596            prompt();
597            count = 0;
598            break;
[747]599        case '\t':                       // tabulation
[640]600            // do nothing
601            break;
[747]602        case '\03':                      // ^C
[640]603            giet_tty_printf("^C\n");
604            prompt();
605            count = 0;
606            break;
[747]607        default:                         // regular character
[640]608            if (count < sizeof(buf) - 1)
609            {
610                giet_tty_printf("%c", c);
611                buf[count] = c;
612                count++;
613            }
614        }
[589]615    }
616} // end main()
617
618// Local Variables:
[640]619// tab-width: 4
620// c-basic-offset: 4
[589]621// c-file-offsets:((innamespace . 0)(inline-open . 0))
622// indent-tabs-mode: nil
623// End:
[640]624// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
[589]625
Note: See TracBrowser for help on using the repository browser.