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

Last change on this file since 777 was 775, checked in by alain, 9 years ago

Introduce the dump command in shell.

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