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
Line 
1///////////////////////////////////////////////////////////////////////////////////////
2// File   : main.c   (for shell application)
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 "string.h"
11#include "malloc.h"
12
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}
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)
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    }
303} // end main()
304
305// Local Variables:
306// tab-width: 4
307// c-basic-offset: 4
308// c-file-offsets:((innamespace . 0)(inline-open . 0))
309// indent-tabs-mode: nil
310// End:
311// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
312
Note: See TracBrowser for help on using the repository browser.