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

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

Cosmetic.

File size: 16.0 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        ptw = (ptw + 1) % FIFO_SIZE;
69
70        // not recursive
71        recursive = 0;
72    }
73    else if ( (argc == 3) && (strcmp( argv[1] , "-r" ) == 0) )
74    {
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;
80
81        // recursive
82        recursive = 1;
83    }
84    else
85    {
86        giet_tty_printf("  usage : ls [-r] pathname\n");
87        return;
88    }
89
90    // loop on registered directories
91    do
92    {
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        }
100
101        // display directory pathname
102        giet_tty_printf("*** %s ***\n", paths[ptr] );
103
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 );
112
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                }
125
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
152////////////////////////////////////////////
153static void cmd_mkdir(int argc, char** argv)
154{
155    if (argc < 2)
156    {
157        giet_tty_printf("  usage : mkdir pathname\n");
158        return;
159    }
160
161    int ret = giet_fat_mkdir(argv[1]);
162
163    if (ret < 0)
164    {
165        giet_tty_printf("  error : cannot create directory %s / err = %d\n", argv[1], ret);
166    }
167}
168
169/////////////////////////////////////////
170static void cmd_cp(int argc, char** argv)
171{
172    if (argc < 3)
173    {
174        giet_tty_printf("  usage : cp src_pathname dst_pathname>\n");
175        return;
176    }
177
178    char buf[1024];
179    int src_fd = -1;
180    int dst_fd = -1;
181    fat_file_info_t info;
182    int size;
183    int i;
184
185    src_fd = giet_fat_open( argv[1] , O_RDONLY );
186    if (src_fd < 0)
187    {
188        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[1], src_fd);
189        goto exit;
190    }
191
192    giet_fat_file_info(src_fd, &info);
193
194    if (info.is_dir)
195    {
196        giet_tty_printf("  error : %s is a directory\n", argv[1] );
197        goto exit;
198    }
199
200    size = info.size;
201
202    dst_fd = giet_fat_open( argv[2] , O_CREAT | O_TRUNC);
203
204    if (dst_fd < 0)
205    {
206        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[2], dst_fd);
207        goto exit;
208    }
209
210    giet_fat_file_info(dst_fd, &info);
211
212    if (info.is_dir)
213    {
214        giet_tty_printf("  error : %s is a directory\n", argv[2] );  // TODO
215        goto exit;
216    }
217
218    i = 0;
219    while (i < size)
220    {
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        {
228            giet_tty_printf("  error : cannot write on device\n");
229            goto exit;
230        }
231        i += len;
232    }
233
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
241/////////////////////////////////////////
242static void cmd_rm(int argc, char **argv)
243{
244    if (argc < 2)
245    {
246        giet_tty_printf("  usage : rm pathname\n");
247        return;
248    }
249
250    int ret = giet_fat_remove(argv[1], 0);
251
252    if (ret < 0)
253    {
254        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
255    }
256}
257
258////////////////////////////////////////////
259static void cmd_rmdir(int argc, char **argv)
260{
261    if (argc < 2)
262    {
263        giet_tty_printf("  usage : rmdir pathname\n");
264        return;
265    }
266
267    int ret = giet_fat_remove(argv[1], 1);
268    if (ret < 0)
269    {
270        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
271    }
272}
273
274/////////////////////////////////////////
275static void cmd_mv(int argc, char **argv)
276{
277    if (argc < 3)
278    {
279        giet_tty_printf("  usage : %s src_pathname dst_pathname\n", argv[0]);
280        return;
281    }
282
283    int ret = giet_fat_rename(argv[1], argv[2]);
284    if (ret < 0)
285    {
286        giet_tty_printf("error : cannot move %s to %s / err = %d\n", argv[1], argv[2], ret );
287    }
288}
289
290///////////////////////////////////////////
291static void cmd_exec(int argc, char **argv)
292{
293    if (argc < 2)
294    {
295        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
296        return;
297    }
298
299    int ret = giet_exec_application(argv[1]);
300    if ( ret == -1 )
301    {
302        giet_tty_printf("  error : %s not found\n", argv[1] );
303    }
304}
305
306///////////////////////////////////////////
307static void cmd_kill(int argc, char **argv)
308{
309    if (argc < 2)
310    {
311        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
312        return;
313    }
314
315    int ret = giet_kill_application(argv[1]);
316    if ( ret == -1 )
317    {
318        giet_tty_printf("  error : %s not found\n", argv[1] );
319    }
320    if ( ret == -2 )
321    {
322        giet_tty_printf("  error : %s cannot be killed\n", argv[1] );
323    }
324}
325
326/////////////////////////////////////////
327static void cmd_ps(int argc, char** argv)
328{
329    if (argc == 1)
330    {
331        giet_applications_status( NULL );
332    }
333    else
334    {
335        giet_applications_status( argv[1] );
336    }
337}
338
339////////////////////////////////////////////
340static void cmd_pause(int argc, char** argv)
341{
342    if (argc < 3)
343    {
344        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
345        return;
346    }
347
348    giet_pthread_control( THREAD_CMD_PAUSE , argv[1] , argv[2] );
349}
350
351/////////////////////////////////////////////
352static void cmd_resume(int argc, char** argv)
353{
354    if (argc < 3)
355    {
356        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
357        return;
358    }
359
360    giet_pthread_control( THREAD_CMD_RESUME , argv[1] , argv[2] );
361}
362
363/////////////////////////////////////////////
364static void cmd_context(int argc, char** argv)
365{
366    if (argc < 3)
367    {
368        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
369        return;
370    }
371
372    giet_pthread_control( THREAD_CMD_CONTEXT , argv[1] , argv[2] );
373}
374
375/////////////////////////////////////////////
376static void cmd_cat(int argc, char** argv)
377{
378    if (argc != 2)
379    {
380        giet_tty_printf("  usage : cat pathname \n");
381        return;
382    }
383
384    unsigned int     x,y,p;          // processor coordinates
385    unsigned int     fd;             // file descriptor
386    fat_file_info_t  info;           // file info
387    unsigned int     size;           // buffer size (file_size + 1)
388    unsigned int     bytes;          // number of bytes to be mapped 
389    char*            buf = NULL;     // temporary buffer
390
391    // get processor coordinates
392    giet_proc_xyp( &x , &y , &p );
393   
394    // open the file to display   
395    fd = giet_fat_open( argv[1] , 0 );
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
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'
429    buf[size] = 0;
430
431    // display the file content
432    giet_tty_printf("%s", buf );
433
434exit:
435    if ( fd >= 0 )     giet_fat_close( fd );
436    if ( buf != NULL ) giet_fat_munmap( buf , bytes );
437}
438
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
471////////////////////////////////////////////////////////////////////
472struct command_t cmd[] =
473{
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 },
477    { "dump",       "display content of disk sector",       cmd_dump },
478    { "exec",       "start an application",                 cmd_exec },
479    { "help",       "list available commands",              cmd_help },
480    { "kill",       "kill an application (all threads)",    cmd_kill },
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 },
484    { "pause",      "pause a thread",                       cmd_pause },
485    { "ps",         "list all mapped applications status",  cmd_ps },
486    { "resume",     "resume a thread",                      cmd_resume },
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 },
490    { NULL,         NULL,                                   NULL }
491};
492
493// shell
494
495///////////////////////////////////////////////////////////////////
496// This function analyses one command (with arguments)
497///////////////////////////////////////////////////////////////////
498static void parse(char *buf)
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++)
507    {
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        }
520    }
521
522    if (argc > 0)
523    {
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        {
540            giet_tty_printf("undefined command %s\n", argv[0]);
541        }
542    }
543}
544
545////////////////////
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
559    // get a private TTY
560    giet_tty_alloc( 0 );
561    giet_tty_printf( "~~~ shell ~~~\n\n" );
562
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
570    // display first prompt
571    prompt();
572
573    while (1)
574    {
575        giet_tty_getc(&c);
576
577        switch (c)
578        {
579        case '\b':                       // backspace
580            if (count > 0)
581            {
582                giet_tty_printf("\b \b");
583                count--;
584            }
585            break;
586        case '\n':                       // new line
587            giet_tty_printf("\n");
588            if (count > 0)
589            {
590                buf[count] = '\0';
591                parse((char*)&buf);
592            }
593            prompt();
594            count = 0;
595            break;
596        case '\t':                       // tabulation
597            // do nothing
598            break;
599        case '\03':                      // ^C
600            giet_tty_printf("^C\n");
601            prompt();
602            count = 0;
603            break;
604        default:                         // regular character
605            if (count < sizeof(buf) - 1)
606            {
607                giet_tty_printf("%c", c);
608                buf[count] = c;
609                count++;
610            }
611        }
612    }
613} // end main()
614
615// Local Variables:
616// tab-width: 4
617// c-basic-offset: 4
618// c-file-offsets:((innamespace . 0)(inline-open . 0))
619// indent-tabs-mode: nil
620// End:
621// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
622
Note: See TracBrowser for help on using the repository browser.