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

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