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

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

Introduce the dump command in shell.

File size: 13.7 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////
2// File   : shell.c   
3// Date   : july 2015
4// author : Clément Guérin
5///////////////////////////////////////////////////////////////////////////////////////
6// Simple shell for GIET_VM.
7///////////////////////////////////////////////////////////////////////////////////////
8
9#include "stdio.h"
10#include "stdlib.h"
11#include "malloc.h"
12
13#define BUF_SIZE    (256)        // buffer for one command
14#define MAX_ARGS    (32)         // max number of arguments in a command
15
16
17struct command_t
18{
19    char *name;
20    char *desc;
21    void (*fn)(int, char**);
22};
23
24////////////////////////////////////////////////////////////////////////////////
25//  Shell  Commands
26////////////////////////////////////////////////////////////////////////////////
27
28struct command_t cmd[];
29
30///////////////////////////////////////////
31static void cmd_help(int argc, char** argv)
32{
33    int i;
34
35    giet_tty_printf("available commands:\n");
36
37    for (i = 0; cmd[i].name; i++)
38    {
39        giet_tty_printf("\t%s\t : %s\n", cmd[i].name , cmd[i].desc );
40    }
41}
42
43///////////////////////////////////////////
44static void cmd_time(int argc, char** argv)
45{
46    giet_tty_printf(" cycle = %d\n", giet_proctime());
47}
48
49/////////////////////////////////////////
50static void cmd_ls(int argc, char** argv)
51{
52    int            fd;
53    int            rec;
54    char*          pathname;
55    fat_dirent_t   entry;
56
57    if (argc == 2)
58    {
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");
68        return;
69    }
70    else
71    {
72        giet_tty_printf("  usage : ls [-r] pathname\n");
73        return;
74    }
75
76    fd  = giet_fat_opendir( pathname );
77
78    if (fd < 0)
79    {
80        giet_tty_printf("  error : cannot open %s / err = %d)\n", argv[1], fd);
81        return;
82    }
83
84    while (giet_fat_readdir(fd, &entry) == 0)
85    {
86        if (entry.is_dir) giet_tty_printf("dir ");
87        else              giet_tty_printf("file");
88
89        giet_tty_printf(" | size = %d \t| cluster = %x \t| %s\n",
90                        entry.size, entry.cluster, entry.name );
91    }
92
93    giet_fat_closedir(fd);
94}
95
96////////////////////////////////////////////
97static void cmd_mkdir(int argc, char** argv)
98{
99    if (argc < 2)
100    {
101        giet_tty_printf("  usage : mkdir pathname\n");
102        return;
103    }
104
105    int ret = giet_fat_mkdir(argv[1]);
106
107    if (ret < 0)
108    {
109        giet_tty_printf("  error : cannot create directory %s / err = %d\n", argv[1], ret);
110    }
111}
112
113/////////////////////////////////////////
114static void cmd_cp(int argc, char** argv)
115{
116    if (argc < 3)
117    {
118        giet_tty_printf("  usage : cp src_pathname dst_pathname>\n");
119        return;
120    }
121
122    char buf[1024];
123    int src_fd = -1;
124    int dst_fd = -1;
125    fat_file_info_t info;
126    int size;
127    int i;
128
129    src_fd = giet_fat_open( argv[1] , O_RDONLY );
130    if (src_fd < 0)
131    {
132        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[1], src_fd);
133        goto exit;
134    }
135
136    giet_fat_file_info(src_fd, &info);
137
138    if (info.is_dir)
139    {
140        giet_tty_printf("  error : %s is a directory\n", argv[1] );
141        goto exit;
142    }
143
144    size = info.size;
145
146    dst_fd = giet_fat_open( argv[2] , O_CREAT | O_TRUNC);
147
148    if (dst_fd < 0)
149    {
150        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[2], dst_fd);
151        goto exit;
152    }
153
154    giet_fat_file_info(dst_fd, &info);
155
156    if (info.is_dir)
157    {
158        giet_tty_printf("  error : %s is a directory\n", argv[2] );  // TODO
159        goto exit;
160    }
161
162    i = 0;
163    while (i < size)
164    {
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        {
172            giet_tty_printf("  error : cannot write on device\n");
173            goto exit;
174        }
175        i += len;
176    }
177
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
185/////////////////////////////////////////
186static void cmd_rm(int argc, char **argv)
187{
188    if (argc < 2)
189    {
190        giet_tty_printf("  usage : rm pathname\n");
191        return;
192    }
193
194    int ret = giet_fat_remove(argv[1], 0);
195
196    if (ret < 0)
197    {
198        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
199    }
200}
201
202////////////////////////////////////////////
203static void cmd_rmdir(int argc, char **argv)
204{
205    if (argc < 2)
206    {
207        giet_tty_printf("  usage : rmdir pathname\n");
208        return;
209    }
210
211    int ret = giet_fat_remove(argv[1], 1);
212    if (ret < 0)
213    {
214        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
215    }
216}
217
218/////////////////////////////////////////
219static void cmd_mv(int argc, char **argv)
220{
221    if (argc < 3)
222    {
223        giet_tty_printf("  usage : %s src_pathname dst_pathname\n", argv[0]);
224        return;
225    }
226
227    int ret = giet_fat_rename(argv[1], argv[2]);
228    if (ret < 0)
229    {
230        giet_tty_printf("error : cannot move %s to %s / err = %d\n", argv[1], argv[2], ret );
231    }
232}
233
234///////////////////////////////////////////
235static void cmd_exec(int argc, char **argv)
236{
237    if (argc < 2)
238    {
239        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
240        return;
241    }
242
243    int ret = giet_exec_application(argv[1]);
244    if ( ret == -1 )
245    {
246        giet_tty_printf("  error : %s not found\n", argv[1] );
247    }
248}
249
250///////////////////////////////////////////
251static void cmd_kill(int argc, char **argv)
252{
253    if (argc < 2)
254    {
255        giet_tty_printf("  usage : %s vspace_name\n", argv[0]);
256        return;
257    }
258
259    int ret = giet_kill_application(argv[1]);
260    if ( ret == -1 )
261    {
262        giet_tty_printf("  error : %s not found\n", argv[1] );
263    }
264    if ( ret == -2 )
265    {
266        giet_tty_printf("  error : %s cannot be killed\n", argv[1] );
267    }
268}
269
270/////////////////////////////////////////
271static void cmd_ps(int argc, char** argv)
272{
273    if (argc == 1)
274    {
275        giet_applications_status( NULL );
276    }
277    else
278    {
279        giet_applications_status( argv[1] );
280    }
281}
282
283////////////////////////////////////////////
284static void cmd_pause(int argc, char** argv)
285{
286    if (argc < 3)
287    {
288        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
289        return;
290    }
291
292    giet_pthread_control( THREAD_CMD_PAUSE , argv[1] , argv[2] );
293}
294
295/////////////////////////////////////////////
296static void cmd_resume(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
304    giet_pthread_control( THREAD_CMD_RESUME , argv[1] , argv[2] );
305}
306
307/////////////////////////////////////////////
308static void cmd_context(int argc, char** argv)
309{
310    if (argc < 3)
311    {
312        giet_tty_printf("  usage : %s vspace_name thread_name\n", argv[0] );
313        return;
314    }
315
316    giet_pthread_control( THREAD_CMD_CONTEXT , argv[1] , argv[2] );
317}
318
319/////////////////////////////////////////////
320static void cmd_cat(int argc, char** argv)
321{
322    if (argc != 2)
323    {
324        giet_tty_printf("  usage : cat pathname \n");
325        return;
326    }
327
328    unsigned int     x,y,p;          // processor coordinates
329    unsigned int     fd;             // file descriptor
330    fat_file_info_t  info;           // file info
331    unsigned int     size;           // buffer size (file_size + 1)
332    unsigned int     bytes;          // number of bytes to be mapped 
333    char*            buf = NULL;     // temporary buffer
334
335    // get processor coordinates
336    giet_proc_xyp( &x , &y , &p );
337   
338    // open the file to display   
339    fd = giet_fat_open( argv[1] , 0 );
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
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'
373    buf[size] = 0;
374
375    // display the file content
376    giet_tty_printf("%s", buf );
377
378exit:
379    if ( fd >= 0 )     giet_fat_close( fd );
380    if ( buf != NULL ) giet_fat_munmap( buf , bytes );
381}
382
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
415////////////////////////////////////////////////////////////////////
416struct command_t cmd[] =
417{
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 },
421    { "dump",       "display content of disk sector",       cmd_dump },
422    { "exec",       "start an application",                 cmd_exec },
423    { "help",       "list available commands",              cmd_help },
424    { "kill",       "kill an application (all threads)",    cmd_kill },
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 },
428    { "pause",      "pause a thread",                       cmd_pause },
429    { "ps",         "list all mapped applications status",  cmd_ps },
430    { "resume",     "resume a thread",                      cmd_resume },
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 },
434    { NULL,         NULL,                                   NULL }
435};
436
437// shell
438
439///////////////////////////////////////////////////////////////////
440// This function analyses one command (with arguments)
441///////////////////////////////////////////////////////////////////
442static void parse(char *buf)
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++)
451    {
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        }
464    }
465
466    if (argc > 0)
467    {
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        {
484            giet_tty_printf("undefined command %s\n", argv[0]);
485        }
486    }
487}
488
489////////////////////
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
503    // get a private TTY
504    giet_tty_alloc( 0 );
505    giet_tty_printf( "~~~ shell ~~~\n\n" );
506
507    // display first prompt
508    prompt();
509
510    while (1)
511    {
512        giet_tty_getc(&c);
513
514        switch (c)
515        {
516        case '\b':                       // backspace
517            if (count > 0)
518            {
519                giet_tty_printf("\b \b");
520                count--;
521            }
522            break;
523        case '\n':                       // new line
524            giet_tty_printf("\n");
525            if (count > 0)
526            {
527                buf[count] = '\0';
528                parse((char*)&buf);
529            }
530            prompt();
531            count = 0;
532            break;
533        case '\t':                       // tabulation
534            // do nothing
535            break;
536        case '\03':                      // ^C
537            giet_tty_printf("^C\n");
538            prompt();
539            count = 0;
540            break;
541        default:                         // regular character
542            if (count < sizeof(buf) - 1)
543            {
544                giet_tty_printf("%c", c);
545                buf[count] = c;
546                count++;
547            }
548        }
549    }
550} // end main()
551
552// Local Variables:
553// tab-width: 4
554// c-basic-offset: 4
555// c-file-offsets:((innamespace . 0)(inline-open . 0))
556// indent-tabs-mode: nil
557// End:
558// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
559
Note: See TracBrowser for help on using the repository browser.