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

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

Use the giet_fat_mmap() syscall to implement the cat command.

File size: 13.0 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("%d\n", giet_proctime());
47}
48
49/////////////////////////////////////////
50static void cmd_ls(int argc, char** argv)
51{
52    int fd;
53    fat_dirent_t entry;
54
55    if (argc < 2)
56    {
57        giet_tty_printf("  usage : %s <pathname>\n", argv[0]);
58        return;
59    }
60
61    fd = giet_fat_opendir(argv[1]);
62
63    if (fd < 0)
64    {
65        giet_tty_printf("  error : cannot open %s / err = %d)\n", argv[1], fd);
66        return;
67    }
68
69    while (giet_fat_readdir(fd, &entry) == 0)
70    {
71        if (entry.is_dir) giet_tty_printf("dir ");
72        else              giet_tty_printf("file");
73
74        giet_tty_printf(" | size = %d \t| cluster = %x \t| %s\n",
75                        entry.size, entry.cluster, entry.name );
76    }
77
78    giet_fat_closedir(fd);
79}
80
81////////////////////////////////////////////
82static void cmd_mkdir(int argc, char** argv)
83{
84    if (argc < 2)
85    {
86        giet_tty_printf("  usage : %s <path>\n", argv[0]);
87        return;
88    }
89
90    int ret = giet_fat_mkdir(argv[1]);
91
92    if (ret < 0)
93    {
94        giet_tty_printf("  error : cannot create directory %s / err = %d\n", argv[1], ret);
95    }
96}
97
98/////////////////////////////////////////
99static void cmd_cp(int argc, char** argv)
100{
101    if (argc < 3)
102    {
103        giet_tty_printf("  usage : %s <src> <dst>\n", argv[0]);
104        return;
105    }
106
107    char buf[1024];
108    int src_fd = -1;
109    int dst_fd = -1;
110    fat_file_info_t info;
111    int size;
112    int i;
113
114    src_fd = giet_fat_open( argv[1] , O_RDONLY );
115    if (src_fd < 0)
116    {
117        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[1], src_fd);
118        goto exit;
119    }
120
121    giet_fat_file_info(src_fd, &info);
122
123    if (info.is_dir)
124    {
125        giet_tty_printf("  error : %s is a directory\n", argv[1] );
126        goto exit;
127    }
128
129    size = info.size;
130
131    dst_fd = giet_fat_open( argv[2] , O_CREATE | O_TRUNC );
132
133    if (dst_fd < 0)
134    {
135        giet_tty_printf("  error : cannot open %s / err = %d\n", argv[2], dst_fd);
136        goto exit;
137    }
138
139    giet_fat_file_info(dst_fd, &info);
140
141    if (info.is_dir)
142    {
143        giet_tty_printf("error : %s is a directory\n", argv[2] );  // TODO
144        goto exit;
145    }
146
147    i = 0;
148    while (i < size)
149    {
150        int len = (size - i < 1024 ? size - i : 1024);
151        int wlen;
152
153        giet_tty_printf("\rwrite %d/%d (%d%%)", i, size, 100*i/size);
154
155        len = giet_fat_read(src_fd, &buf, len);
156        wlen = giet_fat_write(dst_fd, &buf, len);
157        if (wlen != len)
158        {
159            giet_tty_printf("  error : cannot write on device\n");
160            goto exit;
161        }
162        i += len;
163    }
164    giet_tty_printf("\n");
165
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
173/////////////////////////////////////////
174static void cmd_rm(int argc, char **argv)
175{
176    if (argc < 2)
177    {
178        giet_tty_printf("  usage : %s <file>\n", argv[0]);
179        return;
180    }
181
182    int ret = giet_fat_remove(argv[1], 0);
183
184    if (ret < 0)
185    {
186        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
187    }
188}
189
190////////////////////////////////////////////
191static void cmd_rmdir(int argc, char **argv)
192{
193    if (argc < 2)
194    {
195        giet_tty_printf("  usage : %s <pathname>\n", argv[0]);
196        return;
197    }
198
199    int ret = giet_fat_remove(argv[1], 1);
200    if (ret < 0)
201    {
202        giet_tty_printf("  error : cannot remove %s / err = %d\n", argv[1], ret );
203    }
204}
205
206/////////////////////////////////////////
207static void cmd_mv(int argc, char **argv)
208{
209    if (argc < 3)
210    {
211        giet_tty_printf("  usage : %s <src> <dst>\n", argv[0]);
212        return;
213    }
214
215    int ret = giet_fat_rename(argv[1], argv[2]);
216    if (ret < 0)
217    {
218        giet_tty_printf("error : cannot move %s to %s / err = %d\n", argv[1], argv[2], ret );
219    }
220}
221
222///////////////////////////////////////////
223static void cmd_exec(int argc, char **argv)
224{
225    if (argc < 2)
226    {
227        giet_tty_printf("  usage : %s <vspace_name>\n", argv[0]);
228        return;
229    }
230
231    int ret = giet_exec_application(argv[1]);
232    if ( ret == -1 )
233    {
234        giet_tty_printf("  error : %s not found\n", argv[1] );
235    }
236}
237
238///////////////////////////////////////////
239static void cmd_kill(int argc, char **argv)
240{
241    if (argc < 2)
242    {
243        giet_tty_printf("  usage : %s <vspace_name>\n", argv[0]);
244        return;
245    }
246
247    int ret = giet_kill_application(argv[1]);
248    if ( ret == -1 )
249    {
250        giet_tty_printf("  error : %s not found\n", argv[1] );
251    }
252    if ( ret == -2 )
253    {
254        giet_tty_printf("  error : %s cannot be killed\n", argv[1] );
255    }
256}
257
258/////////////////////////////////////////
259static void cmd_ps(int argc, char** argv)
260{
261    if (argc == 1)
262    {
263        giet_applications_status( NULL );
264    }
265    else
266    {
267        giet_applications_status( argv[1] );
268    }
269}
270
271////////////////////////////////////////////
272static void cmd_pause(int argc, char** argv)
273{
274    if (argc < 3)
275    {
276        giet_tty_printf("  usage : %s <vspace_name> <thread_name>\n", argv[0] );
277        return;
278    }
279
280    giet_pthread_control( THREAD_CMD_PAUSE , argv[1] , argv[2] );
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] );
289        return;
290    }
291
292    giet_pthread_control( THREAD_CMD_RESUME , argv[1] , argv[2] );
293}
294
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
304    giet_pthread_control( THREAD_CMD_CONTEXT , argv[1] , argv[2] );
305}
306
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    }
315
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     bytes;          // number of bytes to be mapped 
321    char*            buf = NULL;     // 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] , 0 );
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    // 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/*
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    }
369    // load the file
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    }
377*/
378    // set terminating '0'
379    buf[size] = 0;
380
381    // display the file content
382    giet_tty_printf("%s", buf );
383
384exit:
385    if ( fd >= 0 )     giet_fat_close( fd );
386    if ( buf != NULL ) giet_fat_munmap( buf , bytes );
387}
388
389////////////////////////////////////////////////////////////////////
390struct command_t cmd[] =
391{
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 },
396    { "help",       "list available commands",              cmd_help },
397    { "kill",       "kill an application (all threads)",    cmd_kill },
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 },
401    { "pause",      "pause a thread",                       cmd_pause },
402    { "ps",         "list all mapped applications status",  cmd_ps },
403    { "resume",     "resume a thread",                      cmd_resume },
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 },
407    { NULL,         NULL,                                   NULL }
408};
409
410// shell
411
412///////////////////////////////////////////////////////////////////
413// This function analyses one command (with arguments)
414///////////////////////////////////////////////////////////////////
415static void parse(char *buf)
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++)
424    {
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        }
437    }
438
439    if (argc > 0)
440    {
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        {
457            giet_tty_printf("undefined command %s\n", argv[0]);
458        }
459    }
460}
461
462////////////////////
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
476    // get a private TTY
477    giet_tty_alloc( 0 );
478    giet_tty_printf( "~~~ shell ~~~\n\n" );
479
480    // display first prompt
481    prompt();
482
483    while (1)
484    {
485        giet_tty_getc(&c);
486
487        switch (c)
488        {
489        case '\b':                       // backspace
490            if (count > 0)
491            {
492                giet_tty_printf("\b \b");
493                count--;
494            }
495            break;
496        case '\n':                       // new line
497            giet_tty_printf("\n");
498            if (count > 0)
499            {
500                buf[count] = '\0';
501                parse((char*)&buf);
502            }
503            prompt();
504            count = 0;
505            break;
506        case '\t':                       // tabulation
507            // do nothing
508            break;
509        case '\03':                      // ^C
510            giet_tty_printf("^C\n");
511            prompt();
512            count = 0;
513            break;
514        default:                         // regular character
515            if (count < sizeof(buf) - 1)
516            {
517                giet_tty_printf("%c", c);
518                buf[count] = c;
519                count++;
520            }
521        }
522    }
523} // end main()
524
525// Local Variables:
526// tab-width: 4
527// c-basic-offset: 4
528// c-file-offsets:((innamespace . 0)(inline-open . 0))
529// indent-tabs-mode: nil
530// End:
531// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
532
Note: See TracBrowser for help on using the repository browser.