summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/user/app/shell/builtins.c105
-rw-r--r--src/user/app/shell/builtins.h9
-rw-r--r--src/user/app/shell/shell.c45
3 files changed, 93 insertions, 66 deletions
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c
index 3a19a2f..e272cf3 100644
--- a/src/user/app/shell/builtins.c
+++ b/src/user/app/shell/builtins.c
@@ -4,54 +4,55 @@
#include <string.h>
#include <unistd.h>
-void cmd_cat_ls(const char *args, bool ls) {
+static void cmd_cat(int argc, const char **argv) {
+ // TODO loop over argv
+
FILE *file;
static char buf[512];
- int len; // first used for strlen(args), then length of buffer
-
- if (args) {
- len = strlen(args);
- memcpy(buf, args, len + 1); // no overflow check - the shell is just a PoC
- if (ls) { // paths to directories always have a trailing slash
- if (buf[len-1] != '/') {
- buf[len] = '/';
- buf[len+1] = '\0';
- }
- }
-
- file = fopen(buf, "r");
- } else if (ls) { /* ls default argument */
- file = fopen("/", "r");
- } else { /* cat default argument */
+ if (argv[1])
+ file = fopen(argv[1], "r");
+ else
file = file_clone(stdin);
- }
if (!file) {
eprintf("couldn't open");
return;
}
- while (!feof(file)) {
+ for (;;) {
int len = fread(buf, 1, sizeof buf, file);
if (len <= 0) break;
-
- if (ls) {
- for (int i = 0; i < len; i++)
- if (buf[i] == '\0') buf[i] = '\n';
- }
fwrite(buf, 1, len, stdout);
}
fclose(file);
}
-void cmd_hexdump(const char *args) {
+static void cmd_echo(int argc, const char **argv) {
+ bool newline = true;
+ int i = 1;
+
+ if (!strcmp("-n", argv[i])) {
+ i++;
+ newline = false;
+ }
+
+ printf("%s", argv[i++]);
+ for (; argv[i]; i++)
+ printf(" %s", argv[i]);
+ if (newline)
+ printf("\n");
+}
+
+void cmd_hexdump(int argc, const char **argv) {
+ // TODO loop over argv
+ // TODO use fopen/fread
static uint8_t buf[512];
int fd, len;
- fd = _syscall_open(args, strlen(args), 0);
+ fd = _syscall_open(argv[1], strlen(argv[1]), 0);
if (fd < 0) {
- eprintf("couldn't open %s", args);
+ eprintf("couldn't open %s", argv[1]);
return;
}
@@ -77,11 +78,55 @@ void cmd_hexdump(const char *args) {
close(fd);
}
-void cmd_touch(const char *args) {
- int fd = _syscall_open(args, strlen(args), OPEN_CREATE);
+static void cmd_ls(int argc, const char **argv) {
+ // TODO loop over argv
+ FILE *file;
+ static char buf[512];
+
+ if (argv[1]) {
+ int len = strlen(argv[1]);
+ memcpy(buf, argv[1], len + 1); // TODO no overflow check
+
+ if (buf[len-1] != '/') {
+ buf[len] = '/';
+ buf[len+1] = '\0';
+ }
+
+ file = fopen(buf, "r");
+ } else {
+ file = fopen("/", "r");
+ }
+
+ if (!file) {
+ eprintf("couldn't open");
+ return;
+ }
+
+ for (;;) {
+ int len = fread(buf, 1, sizeof buf, file);
+ if (len <= 0) break;
+ for (int i = 0; i < len; i++)
+ if (buf[i] == '\0') buf[i] = '\n';
+ fwrite(buf, 1, len, stdout);
+ }
+ fclose(file);
+}
+
+static void cmd_touch(int argc, const char **argv) {
+ // TODO loop over argv
+ int fd = _syscall_open(argv[1], strlen(argv[1]), OPEN_CREATE);
if (fd < 0) {
- eprintf("couldn't touch %s\n", args);
+ eprintf("couldn't touch %s\n", argv[1]);
return;
}
close(fd);
}
+
+struct builtin builtins[] = {
+ {"cat", cmd_cat},
+ {"echo", cmd_echo},
+ {"hexdump", cmd_hexdump},
+ {"ls", cmd_ls},
+ {"touch", cmd_touch},
+ {NULL, NULL},
+};
diff --git a/src/user/app/shell/builtins.h b/src/user/app/shell/builtins.h
index bb52cef..aa2cd8c 100644
--- a/src/user/app/shell/builtins.h
+++ b/src/user/app/shell/builtins.h
@@ -2,6 +2,9 @@
#include <camellia/syscalls.h>
#include <stdbool.h>
-void cmd_cat_ls(const char *args, bool ls);
-void cmd_hexdump(const char *args);
-void cmd_touch(const char *args);
+struct builtin {
+ const char *name;
+ void (*fn)(int argc, const char **argv);
+};
+
+extern struct builtin builtins[];
diff --git a/src/user/app/shell/shell.c b/src/user/app/shell/shell.c
index 8bfe105..f47dc8d 100644
--- a/src/user/app/shell/shell.c
+++ b/src/user/app/shell/shell.c
@@ -36,8 +36,8 @@ static void run(char *cmd) {
char *argv[ARGV_MAX];
struct redir redir;
- int ret = parse(cmd, argv, ARGV_MAX, &redir);
- if (ret < 0) {
+ int argc = parse(cmd, argv, ARGV_MAX, &redir);
+ if (argc < 0) {
eprintf("error parsing command");
return;
}
@@ -63,39 +63,18 @@ static void run(char *cmd) {
exit(0);
}
- if (!strcmp(argv[0], "echo")) {
- printf("%s", argv[1]);
- for (int i = 2; argv[i]; i++)
- printf(" %s", argv[i]);
- printf("\n");
- } else if (!strcmp(argv[0], "fork")) {
- main();
- } else if (!strcmp(argv[0], "cat")) {
- // TODO better argv handling
- cmd_cat_ls(argv[1], false);
- } else if (!strcmp(argv[0], "ls")) {
- cmd_cat_ls(argv[1], true);
- } else if (!strcmp(argv[0], "hexdump")) {
- cmd_hexdump(argv[1]);
- } else if (!strcmp(argv[0], "catall")) {
- const char *files[] = {
- "/init/fake.txt",
- "/init/1.txt", "/init/2.txt",
- "/init/dir/3.txt", NULL};
- for (int i = 0; files[i]; i++) {
- printf("%s:\n", files[i]);
- cmd_cat_ls(files[i], false);
- printf("\n");
+ for (struct builtin *iter = builtins; iter->name; iter++) {
+ if (!strcmp(argv[0], iter->name)) {
+ iter->fn(argc, argv);
+ exit(0);
}
- } else if (!strcmp(argv[0], "touch")) {
- cmd_touch(argv[1]);
+ }
+
+ execp(argv);
+ if (errno == EINVAL) {
+ eprintf("%s isn't a valid executable\n", argv[0]);
} else {
- execp(argv);
- if (errno == EINVAL) {
- eprintf("%s isn't a valid executable\n", argv[0]);
- } else {
- eprintf("unknown command: %s\n", argv[0]);
- }
+ eprintf("unknown command: %s\n", argv[0]);
}
exit(0); /* kills the subprocess */
}