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

Last change on this file since 782 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
Line 
1///////////////////////////////////////////////////////////////////////////////////////
2// File    : shell.c   
3// Date    : july 2015
4// authors : Clément Guérin and Alain Greiner
5///////////////////////////////////////////////////////////////////////////////////////
6// Simple shell for the GIET_VM.
7///////////////////////////////////////////////////////////////////////////////////////
8
9#include "stdio.h"
10#include "stdlib.h"
11#include "malloc.h"
12#include "string.h"
13
14#define BUF_SIZE    (256)        // buffer for one command
15#define MAX_ARGS    (32)         // max number of arguments in a command
16#define FIFO_SIZE   (1024)       // FIFO depth for recursive ls
17
18
19struct command_t
20{
21    char *name;
22    char *desc;
23    void (*fn)(int, char**);
24};
25
26////////////////////////////////////////////////////////////////////////////////
27//  Shell  Commands
28////////////////////////////////////////////////////////////////////////////////
29
30struct command_t cmd[];
31
32///////////////////////////////////////////
33static void cmd_help(int argc, char** argv)
34{
35    int i;
36
37    giet_tty_printf("available commands:\n");
38
39    for (i = 0; cmd[i].name; i++)
40    {
41        giet_tty_printf("\t%s\t : %s\n", cmd[i].name , cmd[i].desc );
42    }
43}
44
45///////////////////////////////////////////
46static void cmd_time(int argc, char** argv)
47{
48    giet_tty_printf(" cycle = %d\n", giet_proctime());
49}
50
51
52/////////////////////////////////////////
53static void cmd_ls(int argc, char** argv)
54{
55    fat_dirent_t    entry;
56    unsigned int    recursive;
57    char*           paths[FIFO_SIZE];
58    unsigned int    ptr = 0;
59    unsigned int    ptw = 0;
60
61    // analyse arguments
62    if (argc == 2)
63    {
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;
75    }
76    else if ( (argc == 3) && (strcmp( argv[1] , "-r" ) == 0) )
77    {
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;
83
84        // recursive
85        recursive = 1;
86    }
87    else
88    {
89        giet_tty_printf("  usage : ls [-r] pathname\n");
90        return;
91    }
92
93    // loop on registered directories
94    do
95    {
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        }
103
104        // display directory pathname
105        giet_tty_printf("*** %s ***\n", paths[ptr] );
106
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 );
115
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                }
128
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
155////////////////////////////////////////////
156static void cmd_mkdir(int argc, char** argv)
157{
158    if (argc < 2)
159    {
160        giet_tty_printf("  usage : mkdir pathname\n");
161        return;
162    }
163
164    int ret = giet_fat_mkdir(argv[1]);
165
166    if (ret < 0)
167    {
168        giet_tty_printf("  error : cannot create directory %s / err = %d\n", argv[1], ret);
169    }
170}
171
172/////////////////////////////////////////
173static void cmd_cp(int argc, char** argv)
174{
175    if (argc < 3)
176    {
177        giet_tty_printf("  usage : cp src_pathname dst_pathname>\n");
178        return;
179    }
180
181    char buf[1024];
182    int src_fd = -1;
183    int dst_fd = -1;
184    fat_file_info_t info;
185    int size;
186    int i;
187
188    src_fd = giet_fat_open( argv[1] , O_RDONLY );
189    if (src_fd < 0)
190    {
191        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[1], src_fd);
192        goto exit;
193    }
194
195    giet_fat_file_info(src_fd, &info);
196
197    if (info.is_dir)
198    {
199        giet_tty_printf("  error : %s is a directory\n", argv[1] );
200        goto exit;
201    }
202
203    size = info.size;
204
205    dst_fd = giet_fat_open( argv[2] , O_CREAT | O_TRUNC);
206
207    if (dst_fd < 0)
208    {
209        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[2], dst_fd);
210        goto exit;
211    }
212
213    giet_fat_file_info(dst_fd, &info);
214
215    if (info.is_dir)
216    {
217        giet_tty_printf("  error : %s is a directory\n", argv[2] );  // TODO
218        goto exit;
219    }
220
221    i = 0;
222    while (i < size)
223    {
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        {
231            giet_tty_printf("  error : cannot write on device\n");
232            goto exit;
233        }
234        i += len;
235    }
236
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
244/////////////////////////////////////////
245static void cmd_rm(int argc, char **argv)
246{
247    if (argc < 2)
248    {
249        giet_tty_printf("  usage : rm pathname\n");
250        return;
251    }
252
253    int ret = giet_fat_remove(argv[1], 0);
254
255    if (ret < 0)
256    {
257        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
258    }
259}
260
261////////////////////////////////////////////
262static void cmd_rmdir(int argc, char **argv)
263{
264    if (argc < 2)
265    {
266        giet_tty_printf("  usage : rmdir pathname\n");
267        return;
268    }
269
270    int ret = giet_fat_remove(argv[1], 1);
271    if (ret < 0)
272    {
273        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
274    }
275}
276
277/////////////////////////////////////////
278static void cmd_mv(int argc, char **argv)
279{
280    if (argc < 3)
281    {
282        giet_tty_printf("  usage : %s src_pathname dst_pathname\n", argv[0]);
283        return;
284    }
285
286    int ret = giet_fat_rename(argv[1], argv[2]);
287    if (ret < 0)
288    {
289        giet_tty_printf("error : cannot move %s to %s / err = %d\n", argv[1], argv[2], ret );
290    }
291}
292
293///////////////////////////////////////////
294static void cmd_exec(int argc, char **argv)
295{
296    if (argc < 2)
297    {
298        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
299        return;
300    }
301
302    int ret = giet_exec_application(argv[1]);
303    if ( ret == -1 )
304    {
305        giet_tty_printf("  error : %s not found\n", argv[1] );
306    }
307}
308
309///////////////////////////////////////////
310static void cmd_kill(int argc, char **argv)
311{
312    if (argc < 2)
313    {
314        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
315        return;
316    }
317
318    int ret = giet_kill_application(argv[1]);
319    if ( ret == -1 )
320    {
321        giet_tty_printf("  error : %s not found\n", argv[1] );
322    }
323    if ( ret == -2 )
324    {
325        giet_tty_printf("  error : %s cannot be killed\n", argv[1] );
326    }
327}
328
329/////////////////////////////////////////
330static void cmd_ps(int argc, char** argv)
331{
332    if (argc == 1)
333    {
334        giet_applications_status( NULL );
335    }
336    else
337    {
338        giet_applications_status( argv[1] );
339    }
340}
341
342////////////////////////////////////////////
343static void cmd_pause(int argc, char** argv)
344{
345    if (argc < 3)
346    {
347        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
348        return;
349    }
350
351    giet_pthread_control( THREAD_CMD_PAUSE , argv[1] , argv[2] );
352}
353
354/////////////////////////////////////////////
355static void cmd_resume(int argc, char** argv)
356{
357    if (argc < 3)
358    {
359        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
360        return;
361    }
362
363    giet_pthread_control( THREAD_CMD_RESUME , argv[1] , argv[2] );
364}
365
366/////////////////////////////////////////////
367static void cmd_context(int argc, char** argv)
368{
369    if (argc < 3)
370    {
371        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
372        return;
373    }
374
375    giet_pthread_control( THREAD_CMD_CONTEXT , argv[1] , argv[2] );
376}
377
378/////////////////////////////////////////////
379static void cmd_cat(int argc, char** argv)
380{
381    if (argc != 2)
382    {
383        giet_tty_printf("  usage : cat pathname \n");
384        return;
385    }
386
387    unsigned int     x,y,p;          // processor coordinates
388    unsigned int     fd;             // file descriptor
389    fat_file_info_t  info;           // file info
390    unsigned int     size;           // buffer size (file_size + 1)
391    unsigned int     bytes;          // number of bytes to be mapped 
392    char*            buf = NULL;     // temporary buffer
393
394    // get processor coordinates
395    giet_proc_xyp( &x , &y , &p );
396   
397    // open the file to display   
398    fd = giet_fat_open( argv[1] , 0 );
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
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'
432    buf[size] = 0;
433
434    // display the file content
435    giet_tty_printf("%s", buf );
436
437exit:
438    if ( fd >= 0 )     giet_fat_close( fd );
439    if ( buf != NULL ) giet_fat_munmap( buf , bytes );
440}
441
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
474////////////////////////////////////////////////////////////////////
475struct command_t cmd[] =
476{
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 },
480    { "dump",       "display content of disk sector",       cmd_dump },
481    { "exec",       "start an application",                 cmd_exec },
482    { "help",       "list available commands",              cmd_help },
483    { "kill",       "kill an application (all threads)",    cmd_kill },
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 },
487    { "pause",      "pause a thread",                       cmd_pause },
488    { "ps",         "list all mapped applications status",  cmd_ps },
489    { "resume",     "resume a thread",                      cmd_resume },
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 },
493    { NULL,         NULL,                                   NULL }
494};
495
496// shell
497
498///////////////////////////////////////////////////////////////////
499// This function analyses one command (with arguments)
500///////////////////////////////////////////////////////////////////
501static void parse(char *buf)
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++)
510    {
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        }
523    }
524
525    if (argc > 0)
526    {
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        {
543            giet_tty_printf("undefined command %s\n", argv[0]);
544        }
545    }
546}
547
548////////////////////
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
562    // get a private TTY
563    giet_tty_alloc( 0 );
564    giet_tty_printf( "~~~ shell ~~~\n\n" );
565
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
573    // display first prompt
574    prompt();
575
576    while (1)
577    {
578        giet_tty_getc(&c);
579
580        switch (c)
581        {
582        case '\b':                       // backspace
583            if (count > 0)
584            {
585                giet_tty_printf("\b \b");
586                count--;
587            }
588            break;
589        case '\n':                       // new line
590            giet_tty_printf("\n");
591            if (count > 0)
592            {
593                buf[count] = '\0';
594                parse((char*)&buf);
595            }
596            prompt();
597            count = 0;
598            break;
599        case '\t':                       // tabulation
600            // do nothing
601            break;
602        case '\03':                      // ^C
603            giet_tty_printf("^C\n");
604            prompt();
605            count = 0;
606            break;
607        default:                         // regular character
608            if (count < sizeof(buf) - 1)
609            {
610                giet_tty_printf("%c", c);
611                buf[count] = c;
612                count++;
613            }
614        }
615    }
616} // end main()
617
618// Local Variables:
619// tab-width: 4
620// c-basic-offset: 4
621// c-file-offsets:((innamespace . 0)(inline-open . 0))
622// indent-tabs-mode: nil
623// End:
624// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
625
Note: See TracBrowser for help on using the repository browser.