source: soft/giet_vm/applications/shell/main.c @ 640

Last change on this file since 640 was 640, checked in by guerin, 9 years ago

shell: initial interactive shell

File size: 6.5 KB
RevLine 
[589]1///////////////////////////////////////////////////////////////////////////////////////
2// File   : main.c   (for shell application)
[640]3// Date   : july 2015
4// author : Clément Guérin
[589]5///////////////////////////////////////////////////////////////////////////////////////
[640]6// Simple shell for GIET_VM.
[589]7///////////////////////////////////////////////////////////////////////////////////////
8
9#include "stdio.h"
[640]10#include "string.h"
[589]11#include "malloc.h"
12
[640]13#define BUF_SIZE    (256)
14#define MAX_ARGS    (32)
[589]15
[640]16struct command_t
17{
18    char *name;
19    void (*fn)(int, char**);
20};
[589]21
[640]22////////////////////////////////////////////////////////////////////////////////
23//// commands
24
25struct command_t cmd[];
26
27static void cmd_help(int argc, char** argv)
[589]28{
[640]29    int i;
[589]30
[640]31    giet_tty_printf("available commands:\n");
[610]32
[640]33    for (i = 0; cmd[i].name; i++)
[589]34    {
[640]35        giet_tty_printf("\t%s\n", cmd[i].name);
[589]36    }
[640]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)
[589]47    {
[640]48        giet_tty_printf("%s <path>\n", argv[0]);
49        return;
[589]50    }
51
[640]52    giet_fat_list(argv[1]);
53}
54
55static void cmd_mkdir(int argc, char** argv)
56{
57    if (argc < 2)
[589]58    {
[640]59        giet_tty_printf("%s <path>\n", argv[0]);
60        return;
[589]61    }
[640]62
63    int ret = giet_fat_mkdir(argv[1]);
64    if (ret < 0)
[589]65    {
[640]66        giet_tty_printf("can't create directory (err=%d)\n", ret);
[589]67    }
[640]68}
[589]69
[640]70static void cmd_cp(int argc, char** argv)
71{
72    if (argc < 3)
[589]73    {
[640]74        giet_tty_printf("%s <src> <dst>\n", argv[0]);
75        return;
[589]76    }
77
[640]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)
[589]87    {
[640]88        giet_tty_printf("can't open %s (err=%d)\n", argv[1], src_fd);
89        goto exit;
[589]90    }
[640]91
92    giet_fat_file_info(src_fd, &info);
93    if (info.is_dir)
[589]94    {
[640]95        giet_tty_printf("can't copy a directory\n", argv[1]);
96        goto exit;
[589]97    }
[640]98    size = info.size;
[589]99
[640]100    dst_fd = giet_fat_open( argv[2] , O_CREATE ); // TODO O_TRUNC
101    if (dst_fd < 0)
[589]102    {
[640]103        giet_tty_printf("can't open %s (err=%d)\n", argv[2], src_fd);
104        goto exit;
[589]105    }
106
[640]107    giet_fat_file_info(dst_fd, &info);
108    if (info.is_dir)
[589]109    {
[640]110        giet_tty_printf("can't copy to a directory\n", argv[2]); // TODO
111        goto exit;
[589]112    }
[640]113
114    i = 0;
115    while (i < size)
[589]116    {
[640]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);
[589]129    }
130
[640]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)
[589]141    {
[640]142        giet_tty_printf("%s <file>\n", argv[0]);
143        return;
[589]144    }
[640]145
146    int ret = giet_fat_remove(argv[1], 0);
147    if (ret < 0)
[589]148    {
[640]149        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
[589]150    }
[640]151}
[589]152
[640]153static void cmd_rmdir(int argc, char **argv)
154{
155    if (argc < 2)
[589]156    {
[640]157        giet_tty_printf("%s <path>\n", argv[0]);
158        return;
[589]159    }
[640]160
161    int ret = giet_fat_remove(argv[1], 1);
162    if (ret < 0)
[589]163    {
[640]164        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
[589]165    }
[640]166}
[589]167
[640]168static void cmd_mv(int argc, char **argv)
169{
170    if (argc < 3)
[589]171    {
[640]172        giet_tty_printf("%s <src> <dst>\n", argv[0]);
173        return;
[589]174    }
[640]175
176    int ret = giet_fat_rename(argv[1], argv[2]);
177    if (ret < 0)
[589]178    {
[640]179        giet_tty_printf("can't move %s to %s (err=%d)\n", argv[1], argv[2], ret);
[589]180    }
[640]181}
[589]182
[640]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++)
[589]208    {
[640]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        }
[589]221    }
[640]222
223    if (argc > 0)
[589]224    {
[640]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        }
[589]243    }
[640]244}
[589]245
[640]246static void prompt()
247{
248    giet_tty_printf("# ");
249}
250
251//////////////////////////////////////////
252__attribute__ ((constructor)) void main()
253//////////////////////////////////////////
254{
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());
260    giet_tty_alloc();
261    prompt();
262
263    while (1)
[589]264    {
[640]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        }
[589]302    }
303} // end main()
304
305// Local Variables:
[640]306// tab-width: 4
307// c-basic-offset: 4
[589]308// c-file-offsets:((innamespace . 0)(inline-open . 0))
309// indent-tabs-mode: nil
310// End:
[640]311// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
[589]312
Note: See TracBrowser for help on using the repository browser.