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

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

shell: cp: use carriage return to display progress

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");
102        goto exit;
103    }
104    size = info.size;
105
106    dst_fd = giet_fat_open( argv[2] , O_CREATE | 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"); // 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        giet_tty_printf("\rwrite %d/%d (%d%%)", i, size, 100*i/size);
127
128        len = giet_fat_read(src_fd, &buf, len);
129        wlen = giet_fat_write(dst_fd, &buf, len);
130        if (wlen != len)
131        {
132            giet_tty_printf("\nwrite error\n");
133            goto exit;
134        }
135        i += len;
136    }
137    giet_tty_printf("\n");
138
139exit:
140    if (src_fd >= 0)
141        giet_fat_close(src_fd);
142    if (dst_fd >= 0)
143        giet_fat_close(dst_fd);
144}
145
146static void cmd_rm(int argc, char **argv)
147{
148    if (argc < 2)
149    {
150        giet_tty_printf("%s <file>\n", argv[0]);
151        return;
152    }
153
154    int ret = giet_fat_remove(argv[1], 0);
155    if (ret < 0)
156    {
157        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
158    }
159}
160
161////////////////////////////////////////////
162static void cmd_rmdir(int argc, char **argv)
163{
164    if (argc < 2)
165    {
166        giet_tty_printf("%s <path>\n", argv[0]);
167        return;
168    }
169
170    int ret = giet_fat_remove(argv[1], 1);
171    if (ret < 0)
172    {
173        giet_tty_printf("can't remove %s (err=%d)\n", argv[1], ret);
174    }
175}
176
177/////////////////////////////////////////
178static void cmd_mv(int argc, char **argv)
179{
180    if (argc < 3)
181    {
182        giet_tty_printf("%s <src> <dst>\n", argv[0]);
183        return;
184    }
185
186    int ret = giet_fat_rename(argv[1], argv[2]);
187    if (ret < 0)
188    {
189        giet_tty_printf("can't move %s to %s (err=%d)\n", argv[1], argv[2], ret);
190    }
191}
192
193///////////////////////////////////////////
194static void cmd_exec(int argc, char **argv)
195{
196    if (argc < 2)
197    {
198        giet_tty_printf("%s <pathname>\n", argv[0]);
199        return;
200    }
201
202    int ret = giet_exec_application(argv[1]);
203    if ( ret == -1 )
204    {
205        giet_tty_printf("\n  error : %s not found\n", argv[1] );
206    }
207}
208
209///////////////////////////////////////////
210static void cmd_kill(int argc, char **argv)
211{
212    if (argc < 2)
213    {
214        giet_tty_printf("%s <pathname>\n", argv[0]);
215        return;
216    }
217
218    int ret = giet_kill_application(argv[1]);
219    if ( ret == -1 )
220    {
221        giet_tty_printf("\n  error : %s not found\n", argv[1] );
222    }
223    if ( ret == -2 )
224    {
225        giet_tty_printf("\n  error : %s cannot be killed\n", argv[0] );
226    }
227}
228
229////////////////////////////////////////////////////////////////////
230struct command_t cmd[] =
231{
232    { "help",       cmd_help },
233    { "proctime",   cmd_proctime },
234    { "ls",         cmd_ls },
235    { "mkdir",      cmd_mkdir },
236    { "cp",         cmd_cp },
237    { "rm",         cmd_rm },
238    { "rmdir",      cmd_rmdir },
239    { "mv",         cmd_mv },
240    { "exec",       cmd_exec },
241    { "kill",       cmd_kill },
242    { NULL,         NULL }
243};
244
245// shell
246
247///////////////////////////////////////
248static void parse(char *buf, int count)
249{
250    int argc = 0;
251    char* argv[MAX_ARGS];
252    int i;
253    int len = strlen(buf);
254
255    // build argc/argv
256    for (i = 0; i < len; i++)
257    {
258        if (buf[i] == ' ')
259        {
260            buf[i] = '\0';
261        }
262        else if (i == 0 || buf[i - 1] == '\0')
263        {
264            if (argc < MAX_ARGS)
265            {
266                argv[argc] = &buf[i];
267                argc++;
268            }
269        }
270    }
271
272    if (argc > 0)
273    {
274        int found = 0;
275
276        // try to match typed command with built-ins
277        for (i = 0; cmd[i].name; i++)
278        {
279            if (strcmp(argv[0], cmd[i].name) == 0)
280            {
281                // invoke
282                cmd[i].fn(argc, argv);
283                found = 1;
284                break;
285            }
286        }
287
288        if (!found)
289        {
290            giet_tty_printf("undefined command %s\n", argv[0]);
291        }
292    }
293}
294
295////////////////////
296static void prompt()
297{
298    giet_tty_printf("# ");
299}
300
301//////////////////////////////////////////
302__attribute__ ((constructor)) void main()
303//////////////////////////////////////////
304{
305    char c;
306    char buf[BUF_SIZE];
307    int count = 0;
308
309    giet_shr_printf("\n[SHELL] Enter at cycle %d\n", giet_proctime());
310    giet_tty_alloc();
311    prompt();
312
313    while (1)
314    {
315        giet_tty_getc(&c);
316
317        switch (c)
318        {
319        case '\b':      // backspace
320            if (count > 0)
321            {
322                giet_tty_printf("\b \b");
323                count--;
324            }
325            break;
326        case '\n':      // new line
327            giet_tty_printf("\n");
328            if (count > 0)
329            {
330                buf[count] = '\0';
331                parse((char*)&buf, count);
332            }
333            prompt();
334            count = 0;
335            break;
336        case '\t':      // tabulation
337            // do nothing
338            break;
339        case '\03':     // ^C
340            giet_tty_printf("^C\n");
341            prompt();
342            count = 0;
343            break;
344        default:        // regular character
345            if (count < sizeof(buf) - 1)
346            {
347                giet_tty_printf("%c", c);
348                buf[count] = c;
349                count++;
350            }
351        }
352    }
353} // end main()
354
355// Local Variables:
356// tab-width: 4
357// c-basic-offset: 4
358// c-file-offsets:((innamespace . 0)(inline-open . 0))
359// indent-tabs-mode: nil
360// End:
361// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
362
Note: See TracBrowser for help on using the repository browser.