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

Last change on this file since 646 was 643, checked in by alain, 9 years ago

Introduce the "exec" and "kill" commands in the shell application.

File size: 7.8 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//  Shell  Commands
24////////////////////////////////////////////////////////////////////////////////
25
26struct command_t cmd[];
27
28///////////////////////////////////////////
29static void cmd_help(int argc, char** argv)
30{
31    int i;
32
33    giet_tty_printf("available commands:\n");
34
35    for (i = 0; cmd[i].name; i++)
36    {
37        giet_tty_printf("\t%s\n", cmd[i].name);
38    }
39}
40
41///////////////////////////////////////////////
42static void cmd_proctime(int argc, char** argv)
43{
44    giet_tty_printf("%u\n", giet_proctime());
45}
46
47/////////////////////////////////////////
48static void cmd_ls(int argc, char** argv)
49{
50    if (argc < 2)
51    {
52        giet_tty_printf("%s <path>\n", argv[0]);
53        return;
54    }
55
56    giet_fat_list(argv[1]);
57}
58
59////////////////////////////////////////////
60static void cmd_mkdir(int argc, char** argv)
61{
62    if (argc < 2)
63    {
64        giet_tty_printf("%s <path>\n", argv[0]);
65        return;
66    }
67
68    int ret = giet_fat_mkdir(argv[1]);
69    if (ret < 0)
70    {
71        giet_tty_printf("can't create directory (err=%d)\n", ret);
72    }
73}
74
75/////////////////////////////////////////
76static void cmd_cp(int argc, char** argv)
77{
78    if (argc < 3)
79    {
80        giet_tty_printf("%s <src> <dst>\n", argv[0]);
81        return;
82    }
83
84    char buf[1024];
85    int src_fd = -1;
86    int dst_fd = -1;
87    struct fat_file_info_s info;
88    int size;
89    int i;
90
91    src_fd = giet_fat_open( argv[1] , O_RDONLY );
92    if (src_fd < 0)
93    {
94        giet_tty_printf("can't open %s (err=%d)\n", argv[1], src_fd);
95        goto exit;
96    }
97
98    giet_fat_file_info(src_fd, &info);
99    if (info.is_dir)
100    {
101        giet_tty_printf("can't copy a directory\n", argv[1]);
102        goto exit;
103    }
104    size = info.size;
105
106    dst_fd = giet_fat_open( argv[2] , O_CREATE ); // TODO O_TRUNC
107    if (dst_fd < 0)
108    {
109        giet_tty_printf("can't open %s (err=%d)\n", argv[2], src_fd);
110        goto exit;
111    }
112
113    giet_fat_file_info(dst_fd, &info);
114    if (info.is_dir)
115    {
116        giet_tty_printf("can't copy to a directory\n", argv[2]); // TODO
117        goto exit;
118    }
119
120    i = 0;
121    while (i < size)
122    {
123        int len = (size - i < 1024 ? size - i : 1024);
124        int wlen;
125
126        len = giet_fat_read(src_fd, &buf, len);
127        wlen = giet_fat_write(dst_fd, &buf, len);
128        if (wlen != len)
129        {
130            giet_tty_printf("write error\n");
131            goto exit;
132        }
133        i += len;
134        giet_tty_printf("wrote %d/%d (%d%%)\n", i, size, 100*i/size);
135    }
136
137exit:
138    if (src_fd >= 0)
139        giet_fat_close(src_fd);
140    if (dst_fd >= 0)
141        giet_fat_close(dst_fd);
142}
143
144static void cmd_rm(int argc, char **argv)
145{
146    if (argc < 2)
147    {
148        giet_tty_printf("%s <file>\n", argv[0]);
149        return;
150    }
151
152    int ret = giet_fat_remove(argv[1], 0);
153    if (ret < 0)
154    {
155        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
156    }
157}
158
159////////////////////////////////////////////
160static void cmd_rmdir(int argc, char **argv)
161{
162    if (argc < 2)
163    {
164        giet_tty_printf("%s <path>\n", argv[0]);
165        return;
166    }
167
168    int ret = giet_fat_remove(argv[1], 1);
169    if (ret < 0)
170    {
171        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
172    }
173}
174
175/////////////////////////////////////////
176static void cmd_mv(int argc, char **argv)
177{
178    if (argc < 3)
179    {
180        giet_tty_printf("%s <src> <dst>\n", argv[0]);
181        return;
182    }
183
184    int ret = giet_fat_rename(argv[1], argv[2]);
185    if (ret < 0)
186    {
187        giet_tty_printf("can't move %s to %s (err=%d)\n", argv[1], argv[2], ret);
188    }
189}
190
191///////////////////////////////////////////
192static void cmd_exec(int argc, char **argv)
193{
194    if (argc < 2)
195    {
196        giet_tty_printf("%s <pathname>\n", argv[0]);
197        return;
198    }
199
200    int ret = giet_exec_application(argv[1]);
201    if ( ret == -1 )
202    {
203        giet_tty_printf("\n  error : %s not found\n", argv[1] );
204    }
205}
206
207///////////////////////////////////////////
208static void cmd_kill(int argc, char **argv)
209{
210    if (argc < 2)
211    {
212        giet_tty_printf("%s <pathname>\n", argv[0]);
213        return;
214    }
215
216    int ret = giet_kill_application(argv[1]);
217    if ( ret == -1 )
218    {
219        giet_tty_printf("\n  error : %s not found\n", argv[1] );
220    }
221    if ( ret == -2 )
222    {
223        giet_tty_printf("\n  error : %s cannot be killed\n", argv[0] );
224    }
225}
226
227////////////////////////////////////////////////////////////////////
228struct command_t cmd[] =
229{
230    { "help",       cmd_help },
231    { "proctime",   cmd_proctime },
232    { "ls",         cmd_ls },
233    { "mkdir",      cmd_mkdir },
234    { "cp",         cmd_cp },
235    { "rm",         cmd_rm },
236    { "rmdir",      cmd_rmdir },
237    { "mv",         cmd_mv },
238    { "exec",       cmd_exec },
239    { "kill",       cmd_kill },
240    { NULL,         NULL }
241};
242
243// shell
244
245///////////////////////////////////////
246static void parse(char *buf, int count)
247{
248    int argc = 0;
249    char* argv[MAX_ARGS];
250    int i;
251    int len = strlen(buf);
252
253    // build argc/argv
254    for (i = 0; i < len; i++)
255    {
256        if (buf[i] == ' ')
257        {
258            buf[i] = '\0';
259        }
260        else if (i == 0 || buf[i - 1] == '\0')
261        {
262            if (argc < MAX_ARGS)
263            {
264                argv[argc] = &buf[i];
265                argc++;
266            }
267        }
268    }
269
270    if (argc > 0)
271    {
272        int found = 0;
273
274        // try to match typed command with built-ins
275        for (i = 0; cmd[i].name; i++)
276        {
277            if (strcmp(argv[0], cmd[i].name) == 0)
278            {
279                // invoke
280                cmd[i].fn(argc, argv);
281                found = 1;
282                break;
283            }
284        }
285
286        if (!found)
287        {
288            giet_tty_printf("undefined command %s\n", argv[0]);
289        }
290    }
291}
292
293////////////////////
294static void prompt()
295{
296    giet_tty_printf("# ");
297}
298
299//////////////////////////////////////////
300__attribute__ ((constructor)) void main()
301//////////////////////////////////////////
302{
303    char c;
304    char buf[BUF_SIZE];
305    int count = 0;
306
307    giet_shr_printf("\n[SHELL] Enter at cycle %d\n", giet_proctime());
308    giet_tty_alloc();
309    prompt();
310
311    while (1)
312    {
313        giet_tty_getc(&c);
314
315        switch (c)
316        {
317        case '\b':      // backspace
318            if (count > 0)
319            {
320                giet_tty_printf("\b \b");
321                count--;
322            }
323            break;
324        case '\n':      // new line
325            giet_tty_printf("\n");
326            if (count > 0)
327            {
328                buf[count] = '\0';
329                parse((char*)&buf, count);
330            }
331            prompt();
332            count = 0;
333            break;
334        case '\t':      // tabulation
335            // do nothing
336            break;
337        case '\03':     // ^C
338            giet_tty_printf("^C\n");
339            prompt();
340            count = 0;
341            break;
342        default:        // regular character
343            if (count < sizeof(buf) - 1)
344            {
345                giet_tty_printf("%c", c);
346                buf[count] = c;
347                count++;
348            }
349        }
350    }
351} // end main()
352
353// Local Variables:
354// tab-width: 4
355// c-basic-offset: 4
356// c-file-offsets:((innamespace . 0)(inline-open . 0))
357// indent-tabs-mode: nil
358// End:
359// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
360
Note: See TracBrowser for help on using the repository browser.