[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH 7/7] shell: Unterstützung für Ein-/Ausgabeumleitung
Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
src/modules/c/shell/shell.c | 107 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 105 insertions(+), 2 deletions(-)
diff --git a/src/modules/c/shell/shell.c b/src/modules/c/shell/shell.c
index 8dfd2c0..acca66c 100644
--- a/src/modules/c/shell/shell.c
+++ b/src/modules/c/shell/shell.c
@@ -187,6 +187,45 @@ void shell_read_command(void)
free(cwd);
}
+static bool is_redirection(const char* word, int* stdio_idx, int* flags)
+{
+ *stdio_idx = -1;
+
+ if (!strcmp(word, "<")) {
+ *stdio_idx = 0;
+ *flags = LIO_READ;
+ } else if (!strcmp(word, ">")) {
+ *stdio_idx = 1;
+ *flags = LIO_WRITE | LIO_TRUNC;
+ } else if (!strcmp(word, ">>")) {
+ *stdio_idx = 1;
+ *flags = LIO_WRITE; /* TODO append */
+ } else if (!strcmp(word, "2>")) {
+ *stdio_idx = 2;
+ *flags = LIO_WRITE | LIO_TRUNC;
+ } else if (!strcmp(word, "2>>")) {
+ *stdio_idx = 2;
+ *flags = LIO_WRITE; /* TODO append */
+ }
+
+ return (*stdio_idx != -1);
+}
+
+static int get_stdio_fd(int index)
+{
+ switch (index) {
+ case 0:
+ return file_get_stream(stdin);
+ case 1:
+ return file_get_stream(stdout);
+ case 2:
+ return file_get_stream(stderr);
+ }
+
+ abort();
+ return -1;
+}
+
int handle_command(char* buf)
{
char* args;
@@ -195,6 +234,7 @@ int handle_command(char* buf)
int i;
int in_idx, out_idx;
struct token* tokens;
+ int stdio_orig[3] = { 0 };
int ret;
num_tokens = tokenize_cmdline(buf, NULL, NULL);
@@ -217,8 +257,56 @@ int handle_command(char* buf)
switch (tokens[i].type) {
case TT_OPERATOR:
{
- ret = -1;
- errno = ENOSYS;
+ int stdio_idx, flags;
+ const char* path;
+ lio_resource_t r;
+ lio_stream_t fd;
+ int stdio_fd;
+
+ if (!is_redirection(tokens[i].value, &stdio_idx, &flags)) {
+ fprintf(stderr, "Unbekannter Operator '%s'\n",
+ tokens[i].value);
+ goto found;
+ }
+
+ if (++i >= num_tokens || tokens[i].type != TT_WORD) {
+ fprintf(stderr, "Umleitungsziel erwartet\n");
+ goto found;
+ }
+
+ path = tokens[i].value;
+ r = lio_resource(path, 1);
+ if (r < 0 && (flags & LIO_WRITE)) {
+ lio_resource_t parent;
+ char* dirname = io_split_dirname(path);
+ char* filename = io_split_filename(path);
+
+ if ((parent = lio_resource(dirname, 1)) > 0) {
+ r = lio_mkfile(parent, filename);
+ }
+
+ free(dirname);
+ free(filename);
+ }
+ if (r < 0) {
+ fprintf(stderr, "Kann '%s' nicht öffnen: %s\n",
+ path, strerror(-r));
+ }
+
+ fd = lio_open(r, flags);
+ if (fd < 0) {
+ fprintf(stderr, "Kann '%s' nicht öffnen: %s\n",
+ path, strerror(-fd));
+ goto found;
+ }
+
+ stdio_fd = get_stdio_fd(stdio_idx);
+ if (!stdio_orig[stdio_idx]) {
+ stdio_orig[stdio_idx] = lio_dup(stdio_fd, -1);
+ }
+ fflush(stdout);
+ ret = lio_dup(fd, stdio_fd);
+ lio_close(fd);
if (ret < 0) {
fprintf(stderr,
TMS(fail_dup, "lio_dup() fehlgeschlagen: %s\n"),
@@ -290,6 +378,21 @@ found:
free(args);
free(argv);
+ /* Ausgabeumleitung rückgängig machen */
+ for (i = 0; i < 3; i++) {
+ if (stdio_orig[i]) {
+ int stdio_fd = get_stdio_fd(i);
+
+ fflush(stdout);
+
+ ret = lio_dup(stdio_orig[i], stdio_fd);
+ if (ret < 0) {
+ fprintf(stderr, "lio_dup() fehlgeschlagen: %s\n",
+ strerror(-ret));
+ }
+ }
+ }
+
return 0;
}
--
2.1.4