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

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

Introduce the cat command in the shell.

File size: 12.4 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
[654]131    dst_fd = giet_fat_open( argv[2] , O_CREATE | 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
[747]316    unsigned int     x,y,p;   // processor coordinates
317    unsigned int     fd;             // file descriptor
318    fat_file_info_t  info;           // file info
319    unsigned int     size;           // buffer size (file_size + 1)
320    unsigned int     len;            // number of read bytes from file
321    char*            buf;            // temporary buffer
322
323    // get processor coordinates
324    giet_proc_xyp( &x , &y , &p );
325   
326    // open the file to display   
327    fd = giet_fat_open( argv[1] , O_RDONLY );
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
343    // allocate a temporary buffer for the file
344    heap_init( x , y );
345    buf = (char*)malloc( size ); 
346    if( buf == NULL )
347    {
348        giet_tty_printf("  error : cannot allocate buffer with size = %d\n", size );
349        goto exit;
350    }
351    // load the file and set terminating '0'
352    len = giet_fat_read( fd , buf , size );
353    if ( len != size )
354    {
355        giet_tty_printf("  error : cannot load file %s / size = %d / len = %d\n",
356                        argv[1] , size , len );
357        goto exit;
358    }
359    buf[size] = 0;
360
361    // display the file content
362    giet_tty_printf("\n%s", buf );
363
364exit:
365    if ( fd >= 0 )     giet_fat_close( fd );
366    if ( buf != NULL ) free( buf );
367}
368
[643]369////////////////////////////////////////////////////////////////////
[640]370struct command_t cmd[] =
371{
[747]372    { "cat",        "display file content",                 cmd_cat },
373    { "context",    "display a thread context",             cmd_context },
374    { "cp",         "replicate a file in file system",      cmd_cp },
375    { "exec",       "start an application",                 cmd_exec },
[708]376    { "help",       "list available commands",              cmd_help },
[747]377    { "kill",       "kill an application (all threads)",    cmd_kill },
[708]378    { "ls",         "list content of a directory",          cmd_ls },
379    { "mkdir",      "create a new directory",               cmd_mkdir },
380    { "mv",         "move a file in file system",           cmd_mv },
[747]381    { "pause",      "pause a thread",                       cmd_pause },
[708]382    { "ps",         "list all mapped applications status",  cmd_ps },
383    { "resume",     "resume a thread",                      cmd_resume },
[747]384    { "rm",         "remove a file from file system",       cmd_rm },
385    { "rmdir",      "remove a directory from file system",  cmd_rmdir },
386    { "time",       "return current date",                  cmd_time },
[708]387    { NULL,         NULL,                                   NULL }
[640]388};
389
[643]390// shell
[640]391
[747]392///////////////////////////////////////////////////////////////////
393// This function analyses one command (with arguments)
394///////////////////////////////////////////////////////////////////
[703]395static void parse(char *buf)
[640]396{
397    int argc = 0;
398    char* argv[MAX_ARGS];
399    int i;
400    int len = strlen(buf);
401
402    // build argc/argv
403    for (i = 0; i < len; i++)
[589]404    {
[640]405        if (buf[i] == ' ')
406        {
407            buf[i] = '\0';
408        }
409        else if (i == 0 || buf[i - 1] == '\0')
410        {
411            if (argc < MAX_ARGS)
412            {
413                argv[argc] = &buf[i];
414                argc++;
415            }
416        }
[589]417    }
[640]418
419    if (argc > 0)
[589]420    {
[640]421        int found = 0;
422
423        // try to match typed command with built-ins
424        for (i = 0; cmd[i].name; i++)
425        {
426            if (strcmp(argv[0], cmd[i].name) == 0)
427            {
428                // invoke
429                cmd[i].fn(argc, argv);
430                found = 1;
431                break;
432            }
433        }
434
435        if (!found)
436        {
[643]437            giet_tty_printf("undefined command %s\n", argv[0]);
[640]438        }
[589]439    }
[640]440}
[589]441
[643]442////////////////////
[640]443static void prompt()
444{
445    giet_tty_printf("# ");
446}
447
448//////////////////////////////////////////
449__attribute__ ((constructor)) void main()
450//////////////////////////////////////////
451{
452    char c;
453    char buf[BUF_SIZE];
454    int count = 0;
455
[669]456    // get a private TTY
457    giet_tty_alloc( 0 );
[708]458    giet_tty_printf( "~~~ shell ~~~\n\n" );
[669]459
460    // display first prompt
[640]461    prompt();
462
463    while (1)
[589]464    {
[640]465        giet_tty_getc(&c);
466
467        switch (c)
468        {
[747]469        case '\b':                       // backspace
[640]470            if (count > 0)
471            {
472                giet_tty_printf("\b \b");
473                count--;
474            }
475            break;
[747]476        case '\n':                       // new line
[640]477            giet_tty_printf("\n");
478            if (count > 0)
479            {
480                buf[count] = '\0';
[703]481                parse((char*)&buf);
[640]482            }
483            prompt();
484            count = 0;
485            break;
[747]486        case '\t':                       // tabulation
[640]487            // do nothing
488            break;
[747]489        case '\03':                      // ^C
[640]490            giet_tty_printf("^C\n");
491            prompt();
492            count = 0;
493            break;
[747]494        default:                         // regular character
[640]495            if (count < sizeof(buf) - 1)
496            {
497                giet_tty_printf("%c", c);
498                buf[count] = c;
499                count++;
500            }
501        }
[589]502    }
503} // end main()
504
505// Local Variables:
[640]506// tab-width: 4
507// c-basic-offset: 4
[589]508// c-file-offsets:((innamespace . 0)(inline-open . 0))
509// indent-tabs-mode: nil
510// End:
[640]511// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
[589]512
Note: See TracBrowser for help on using the repository browser.