Ignore:
Timestamp:
Jul 20, 2015, 6:11:40 PM (9 years ago)
Author:
guerin
Message:

shell: initial interactive shell

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/applications/shell/main.c

    r610 r640  
    11///////////////////////////////////////////////////////////////////////////////////////
    22// File   : main.c   (for shell application)
    3 // Date   : february 2014
    4 // author : Alain Greiner
     3// Date   : july 2015
     4// author : Clément Guérin
    55///////////////////////////////////////////////////////////////////////////////////////
    6 // This single thread application plays with files to test the FAT32.
     6// Simple shell for GIET_VM.
    77///////////////////////////////////////////////////////////////////////////////////////
    88
    99#include "stdio.h"
     10#include "string.h"
    1011#include "malloc.h"
    1112
    12 #define NLINES   256
    13 #define NPIXELS  256
    14 
    15 unsigned char buf[NLINES*NPIXELS];
     13#define BUF_SIZE    (256)
     14#define MAX_ARGS    (32)
     15
     16struct command_t
     17{
     18    char *name;
     19    void (*fn)(int, char**);
     20};
     21
     22////////////////////////////////////////////////////////////////////////////////
     23//// commands
     24
     25struct command_t cmd[];
     26
     27static void cmd_help(int argc, char** argv)
     28{
     29    int i;
     30
     31    giet_tty_printf("available commands:\n");
     32
     33    for (i = 0; cmd[i].name; i++)
     34    {
     35        giet_tty_printf("\t%s\n", cmd[i].name);
     36    }
     37}
     38
     39static void cmd_proctime(int argc, char** argv)
     40{
     41    giet_tty_printf("%u\n", giet_proctime());
     42}
     43
     44static void cmd_ls(int argc, char** argv)
     45{
     46    if (argc < 2)
     47    {
     48        giet_tty_printf("%s <path>\n", argv[0]);
     49        return;
     50    }
     51
     52    giet_fat_list(argv[1]);
     53}
     54
     55static void cmd_mkdir(int argc, char** argv)
     56{
     57    if (argc < 2)
     58    {
     59        giet_tty_printf("%s <path>\n", argv[0]);
     60        return;
     61    }
     62
     63    int ret = giet_fat_mkdir(argv[1]);
     64    if (ret < 0)
     65    {
     66        giet_tty_printf("can't create directory (err=%d)\n", ret);
     67    }
     68}
     69
     70static void cmd_cp(int argc, char** argv)
     71{
     72    if (argc < 3)
     73    {
     74        giet_tty_printf("%s <src> <dst>\n", argv[0]);
     75        return;
     76    }
     77
     78    char buf[1024];
     79    int src_fd = -1;
     80    int dst_fd = -1;
     81    struct fat_file_info_s info;
     82    int size;
     83    int i;
     84
     85    src_fd = giet_fat_open( argv[1] , O_RDONLY );
     86    if (src_fd < 0)
     87    {
     88        giet_tty_printf("can't open %s (err=%d)\n", argv[1], src_fd);
     89        goto exit;
     90    }
     91
     92    giet_fat_file_info(src_fd, &info);
     93    if (info.is_dir)
     94    {
     95        giet_tty_printf("can't copy a directory\n", argv[1]);
     96        goto exit;
     97    }
     98    size = info.size;
     99
     100    dst_fd = giet_fat_open( argv[2] , O_CREATE ); // TODO O_TRUNC
     101    if (dst_fd < 0)
     102    {
     103        giet_tty_printf("can't open %s (err=%d)\n", argv[2], src_fd);
     104        goto exit;
     105    }
     106
     107    giet_fat_file_info(dst_fd, &info);
     108    if (info.is_dir)
     109    {
     110        giet_tty_printf("can't copy to a directory\n", argv[2]); // TODO
     111        goto exit;
     112    }
     113
     114    i = 0;
     115    while (i < size)
     116    {
     117        int len = (size - i < 1024 ? size - i : 1024);
     118        int wlen;
     119
     120        len = giet_fat_read(src_fd, &buf, len);
     121        wlen = giet_fat_write(dst_fd, &buf, len);
     122        if (wlen != len)
     123        {
     124            giet_tty_printf("write error\n");
     125            goto exit;
     126        }
     127        i += len;
     128        giet_tty_printf("wrote %d/%d (%d)\n", i, size, 100*i/size);
     129    }
     130
     131exit:
     132    if (src_fd >= 0)
     133        giet_fat_close(src_fd);
     134    if (dst_fd >= 0)
     135        giet_fat_close(dst_fd);
     136}
     137
     138static void cmd_rm(int argc, char **argv)
     139{
     140    if (argc < 2)
     141    {
     142        giet_tty_printf("%s <file>\n", argv[0]);
     143        return;
     144    }
     145
     146    int ret = giet_fat_remove(argv[1], 0);
     147    if (ret < 0)
     148    {
     149        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
     150    }
     151}
     152
     153static void cmd_rmdir(int argc, char **argv)
     154{
     155    if (argc < 2)
     156    {
     157        giet_tty_printf("%s <path>\n", argv[0]);
     158        return;
     159    }
     160
     161    int ret = giet_fat_remove(argv[1], 1);
     162    if (ret < 0)
     163    {
     164        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
     165    }
     166}
     167
     168static void cmd_mv(int argc, char **argv)
     169{
     170    if (argc < 3)
     171    {
     172        giet_tty_printf("%s <src> <dst>\n", argv[0]);
     173        return;
     174    }
     175
     176    int ret = giet_fat_rename(argv[1], argv[2]);
     177    if (ret < 0)
     178    {
     179        giet_tty_printf("can't move %s to %s (err=%d)\n", argv[1], argv[2], ret);
     180    }
     181}
     182
     183struct command_t cmd[] =
     184{
     185    { "help",       cmd_help },
     186    { "proctime",   cmd_proctime },
     187    { "ls",         cmd_ls },
     188    { "mkdir",      cmd_mkdir },
     189    { "cp",         cmd_cp },
     190    { "rm",         cmd_rm },
     191    { "rmdir",      cmd_rmdir },
     192    { "mv",         cmd_mv },
     193    { NULL,         NULL }
     194};
     195
     196////////////////////////////////////////////////////////////////////////////////
     197//// shell
     198
     199static void exec(char *buf, int count)
     200{
     201    int argc = 0;
     202    char* argv[MAX_ARGS];
     203    int i;
     204    int len = strlen(buf);
     205
     206    // build argc/argv
     207    for (i = 0; i < len; i++)
     208    {
     209        if (buf[i] == ' ')
     210        {
     211            buf[i] = '\0';
     212        }
     213        else if (i == 0 || buf[i - 1] == '\0')
     214        {
     215            if (argc < MAX_ARGS)
     216            {
     217                argv[argc] = &buf[i];
     218                argc++;
     219            }
     220        }
     221    }
     222
     223    if (argc > 0)
     224    {
     225        int found = 0;
     226
     227        // try to match typed command with built-ins
     228        for (i = 0; cmd[i].name; i++)
     229        {
     230            if (strcmp(argv[0], cmd[i].name) == 0)
     231            {
     232                // invoke
     233                cmd[i].fn(argc, argv);
     234                found = 1;
     235                break;
     236            }
     237        }
     238
     239        if (!found)
     240        {
     241            giet_tty_printf("unknown command %s\n", argv[0]);
     242        }
     243    }
     244}
     245
     246static void prompt()
     247{
     248    giet_tty_printf("# ");
     249}
    16250
    17251//////////////////////////////////////////
     
    19253//////////////////////////////////////////
    20254{
     255    char c;
     256    char buf[BUF_SIZE];
     257    int count = 0;
     258
     259    giet_shr_printf("\n[SHELL] Enter at cycle %d\n", giet_proctime());
    21260    giet_tty_alloc();
    22 
    23     giet_tty_printf("\n[SHELL] Enter at cycle %d\n", giet_proctime() );
    24 
    25     /////////////// display disk content
    26     giet_fat_list( "/" );
    27     giet_fat_list( "/misc" );
    28     giet_fat_list( "/home" );
    29 
    30     /////////////// open lena_256.raw
    31     int fd_lena = giet_fat_open( "/misc/lena_256.raw" , O_RDONLY );
    32     if (fd_lena < 0 ) 
    33     {
    34         giet_exit("cannot open file lena_256.raw");
    35     }
    36     else
    37     {
    38         giet_tty_printf("\n[SHELL] open lena_256.raw\n");
    39     }
    40 
    41     /////////////// open copy.raw
    42     int fd_copy = giet_fat_open( "/home/copy.raw" , O_CREATE );
    43     if (fd_copy < 0 )
    44     {
    45         giet_exit("cannot open file copy.raw");
    46     }
    47     else
    48     {
    49         giet_tty_printf("\n[SHELL] open copy.raw\n");
    50     }
    51 
    52     //////////////// load lena_256.raw
    53     if ( giet_fat_lseek( fd_lena , 0 , SEEK_SET ) )
    54     {
    55         giet_exit("cannot seek lena_256.raw");
    56     }
    57 
    58     if ( giet_fat_read( fd_lena , buf , NLINES*NPIXELS ) != NLINES*NPIXELS )
    59     {
    60         giet_exit("cannot read lena_256.raw");
    61     }
    62     else
    63     {
    64         giet_tty_printf("\n[SHELL] lena_256.raw loaded from device\n");
    65     }
    66 
    67     ////////////// store copy.raw
    68     if ( giet_fat_lseek( fd_copy , 0 , SEEK_SET ) )
    69     {
    70         giet_exit("cannot seek copy.raw");
    71     }
    72 
    73     if ( giet_fat_write( fd_copy , buf , NLINES*NPIXELS ) != NLINES*NPIXELS )
    74     {
    75         giet_exit("cannot write copy.raw");
    76     }
    77     else
    78     {
    79         giet_tty_printf("\n[SHELL] copy.raw stored to device\n");
    80     }
    81 
    82     ///////////// close lena_256.raw
    83     if ( giet_fat_close( fd_lena ) )
    84     {
    85         giet_exit("cannot close lena_256.raw");
    86     }
    87     else
    88     {
    89         giet_tty_printf("\n[SHELL] lena_256.raw closed\n");
    90     }
    91 
    92     ///////////// close copy.raw
    93     if ( giet_fat_close( fd_copy ) )
    94     {
    95         giet_exit("cannot close copy.raw");
    96     }
    97     else
    98     {
    99         giet_tty_printf("\n[SHELL] copy.raw closed\n");
    100     }
    101 
    102     ////////////// display disk content
    103     giet_fat_list( "/" );
    104     giet_fat_list( "/misc" );
    105     giet_fat_list( "/home" );
    106 
    107     ///////////// rename copy.raw
    108     if ( giet_fat_rename( "/home/copy.raw" , "/misc/copy_lena.raw" ) )
    109     {
    110         giet_exit("cannot rename /home/copy.raw");
    111     }
    112     else
    113     {
    114         giet_tty_printf("\n[SHELL] /home/copy.raw renamed to /misc/copy_lena.raw\n");
    115     }
    116    
    117     ////////////// display disk content
    118     giet_fat_list( "/" );
    119     giet_fat_list( "/misc" );
    120     giet_fat_list( "/home" );
    121 
    122     ///////////// remove home
    123     if ( giet_fat_remove( "/home" , 1 ) )
    124     {
    125         giet_exit("cannot remove /home");
    126     }
    127     else
    128     {
    129         giet_tty_printf("\n[SHELL] /home removed from file system\n");
    130     }
    131    
    132     ////////////// display disk content
    133     giet_fat_list( "/" );
    134     giet_fat_list( "/misc" );
    135 
    136     //////////// create new_home
    137     if ( giet_fat_mkdir( "/new_home" ) )
    138     {
    139         giet_exit("cannot create /new_home");
    140     }
    141     else
    142     {
    143         giet_tty_printf("\n[SHELL] /new_home created in file system\n");
    144     }
    145    
    146     ////////////// display disk content
    147     giet_fat_list( "/" );
    148     giet_fat_list( "/misc" );
    149     giet_fat_list( "/new_home" );
    150 
    151     giet_exit("Completed");
    152 
     261    prompt();
     262
     263    while (1)
     264    {
     265        giet_tty_getc(&c);
     266
     267        switch (c)
     268        {
     269        case '\b':      // backspace
     270            if (count > 0)
     271            {
     272                giet_tty_printf("\b \b");
     273                count--;
     274            }
     275            break;
     276        case '\n':      // new line
     277            giet_tty_printf("\n");
     278            if (count > 0)
     279            {
     280                buf[count] = '\0';
     281                exec((char*)&buf, count);
     282            }
     283            prompt();
     284            count = 0;
     285            break;
     286        case '\t':      // tabulation
     287            // do nothing
     288            break;
     289        case '\03':     // ^C
     290            giet_tty_printf("^C\n");
     291            prompt();
     292            count = 0;
     293            break;
     294        default:        // regular character
     295            if (count < sizeof(buf) - 1)
     296            {
     297                giet_tty_printf("%c", c);
     298                buf[count] = c;
     299                count++;
     300            }
     301        }
     302    }
    153303} // end main()
    154304
    155305// Local Variables:
    156 // tab-width: 3
    157 // c-basic-offset:
     306// tab-width: 4
     307// c-basic-offset: 4
    158308// c-file-offsets:((innamespace . 0)(inline-open . 0))
    159309// indent-tabs-mode: nil
    160310// End:
    161 
    162 // vim: filetype=cpp:expandtab:shiftwidth=3:tabstop=3:softtabstop=3
    163 
    164 
    165 
     311// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
     312
Note: See TracChangeset for help on using the changeset viewer.