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

Last change on this file since 786 was 784, checked in by alain, 9 years ago

Cosmetic.

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