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

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

Introduce the cat command in the shell.

File size: 12.4 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     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
369////////////////////////////////////////////////////////////////////
370struct command_t cmd[] =
371{
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 },
376    { "help",       "list available commands",              cmd_help },
377    { "kill",       "kill an application (all threads)",    cmd_kill },
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 },
381    { "pause",      "pause a thread",                       cmd_pause },
382    { "ps",         "list all mapped applications status",  cmd_ps },
383    { "resume",     "resume a thread",                      cmd_resume },
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 },
387    { NULL,         NULL,                                   NULL }
388};
389
390// shell
391
392///////////////////////////////////////////////////////////////////
393// This function analyses one command (with arguments)
394///////////////////////////////////////////////////////////////////
395static void parse(char *buf)
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++)
404    {
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        }
417    }
418
419    if (argc > 0)
420    {
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        {
437            giet_tty_printf("undefined command %s\n", argv[0]);
438        }
439    }
440}
441
442////////////////////
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
456    // get a private TTY
457    giet_tty_alloc( 0 );
458    giet_tty_printf( "~~~ shell ~~~\n\n" );
459
460    // display first prompt
461    prompt();
462
463    while (1)
464    {
465        giet_tty_getc(&c);
466
467        switch (c)
468        {
469        case '\b':                       // backspace
470            if (count > 0)
471            {
472                giet_tty_printf("\b \b");
473                count--;
474            }
475            break;
476        case '\n':                       // new line
477            giet_tty_printf("\n");
478            if (count > 0)
479            {
480                buf[count] = '\0';
481                parse((char*)&buf);
482            }
483            prompt();
484            count = 0;
485            break;
486        case '\t':                       // tabulation
487            // do nothing
488            break;
489        case '\03':                      // ^C
490            giet_tty_printf("^C\n");
491            prompt();
492            count = 0;
493            break;
494        default:                         // regular character
495            if (count < sizeof(buf) - 1)
496            {
497                giet_tty_printf("%c", c);
498                buf[count] = c;
499                count++;
500            }
501        }
502    }
503} // end main()
504
505// Local Variables:
506// tab-width: 4
507// c-basic-offset: 4
508// c-file-offsets:((innamespace . 0)(inline-open . 0))
509// indent-tabs-mode: nil
510// End:
511// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
512
Note: See TracBrowser for help on using the repository browser.