From 2b90136b3a988807ec40e182fa1f9df8160d05fc Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Wed, 6 May 2020 19:52:07 +0200
Subject: [PATCH] Adding a redirection involving a pty
---
Makefile | 3 +-
include/key_functions.h | 16 +++-
include/redirections.h | 8 +-
include/shell.h | 16 ++--
src/execute.c | 2 +-
src/key_bindings/basic_typing_functions.c | 16 ++++
src/key_bindings/default_bindings.c | 3 +
src/main.c | 1 +
src/prompt.c | 4 +-
src/redirections/pty_pipe.c | 91 +++++++++++++++++++++++
src/redirections/redirections_functions.c | 2 +-
src/shell.c | 55 ++++++--------
12 files changed, 167 insertions(+), 50 deletions(-)
create mode 100644 src/redirections/pty_pipe.c
diff --git a/Makefile b/Makefile
index 9f3e0f7..f23177c 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,8 @@ SRC = src/shell.c \
src/utility/split_commands.c \
src/utility/get_return.c \
src/key_bindings/basic_typing_functions.c \
- src/key_bindings/default_bindings.c
+ src/key_bindings/default_bindings.c \
+ src/redirections/pty_pipe.c
OBJ = $(SRC:%.c=%.o)
OBJ += src/main.o
diff --git a/include/key_functions.h b/include/key_functions.h
index 4edd969..2b9c255 100644
--- a/include/key_functions.h
+++ b/include/key_functions.h
@@ -5,16 +5,24 @@
** bindings
*/
-#include "shell.h"
-
#pragma once
+#include "shell.h"
+
typedef struct key_function
{
const char *name;
int (*run)(int key, buffer_t *command_buffer, env_t *env);
} key_function_t;
-extern const key_function_t key_functions[];
+typedef struct binding
+{
+ int key;
+ int (*func)(int key, buffer_t *command_buffer, env_t *env);
+} binding_t;
-int self_insert_command(int key, buffer_t *command_buffer, env_t *env);
\ No newline at end of file
+extern const key_function_t key_functions[];
+extern const binding_t emacs_bindings[];
+
+int self_insert_command(int key, buffer_t *buffer, env_t *env);
+int newline_command(int key, buffer_t *buffer, env_t *env);
\ No newline at end of file
diff --git a/include/redirections.h b/include/redirections.h
index 6fd2731..17991a5 100644
--- a/include/redirections.h
+++ b/include/redirections.h
@@ -15,7 +15,8 @@ typedef enum redirection_type {
INPUT = 1 << 0,
OUTPUT = 1 << 1,
PIPE = 1 << 2,
- EX_PIPE = 1 << 3
+ EX_PIPE = 1 << 3,
+ PTY = 1 << 4
} redirection_type;
@@ -50,3 +51,8 @@ bool fd_is_used(int fd, redirection *inout);
bool handle_redirections(redirection *inout[2], env_t *env, bool builtin);
bool handle_parent_inout(redirection *inout[2], env_t *env, bool builtin);
+
+
+struct redirection *new_ncurses_pty();
+int pyt_get_fd(redirection *pty);
+void pty_get_output(redirection *pty, env_t *env);
\ No newline at end of file
diff --git a/include/shell.h b/include/shell.h
index bf40ba4..1646cf6 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -7,9 +7,13 @@
typedef struct redirection redirection;
typedef struct env_s env_t;
+typedef struct binding binding_t;
#pragma once
+#define SHELL_NAME "42sh"
+
#include
+#include
typedef struct history_s
{
@@ -26,20 +30,16 @@ typedef struct buffer
char *buffer;
int size;
int pos;
+ int startx;
} buffer_t;
-typedef struct binding
-{
- int key;
- int (*func)(int key, buffer_t *command_buffer, env_t *env);
-} binding_t;
-
typedef struct env_s
{
char **env;
char **vars;
history_t *history;
binding_t *bindings;
+ WINDOW *window;
} env_t;
void start_shell(env_t *env);
@@ -65,6 +65,4 @@ bool envvar_is_valid(const char *str);
#define INVALID_ENV_VAR \
"setenv: Variable name must contain alphanumeric characters.\n"
-#define ERROR 84
-
-extern const binding_t emacs_bindings[];
+#define ERROR 84
\ No newline at end of file
diff --git a/src/execute.c b/src/execute.c
index 1f8f0f3..a23bfa2 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -87,7 +87,7 @@ bool handle_parent_inout(redirection *inout[2], env_t *env, bool builtin)
}
if (inout[1] && inout[1]->type->run_cmd) {
inout[1]->type->run_cmd(inout[1], env);
- return (true);
+ return (!(inout[1]->type->type & PTY));
}
return (false);
}
diff --git a/src/key_bindings/basic_typing_functions.c b/src/key_bindings/basic_typing_functions.c
index bf5a0ee..32db0c5 100644
--- a/src/key_bindings/basic_typing_functions.c
+++ b/src/key_bindings/basic_typing_functions.c
@@ -6,7 +6,9 @@
*/
#include "shell.h"
+#include "builtin.h"
#include "key_functions.h"
+#include
#include
#include
#include
@@ -29,4 +31,18 @@ int self_insert_command(int key, buffer_t *buffer, env_t *env)
strcpy(buffer->buffer + buffer->pos, chars);
buffer->pos += charslen;
return (0);
+}
+
+int newline_command(int key, buffer_t *buffer, env_t *env)
+{
+ int ret;
+
+ if (!buffer->buffer)
+ return (0);
+ add_to_history(buffer->buffer, env);
+ move(getcury(env->window) + 1, 0);
+ ret = eval_raw_cmd(buffer->buffer, env);
+ buffer->buffer[0] = '\0';
+ buffer->pos = 0;
+ return (ret);
}
\ No newline at end of file
diff --git a/src/key_bindings/default_bindings.c b/src/key_bindings/default_bindings.c
index 0a95255..76b4deb 100644
--- a/src/key_bindings/default_bindings.c
+++ b/src/key_bindings/default_bindings.c
@@ -7,13 +7,16 @@
#include "shell.h"
#include "key_functions.h"
+#include
#include
const key_function_t key_functions[] = {
{"self-insert-command", &self_insert_command},
+ {"newline", &newline_command},
{NULL, NULL}
};
const binding_t emacs_bindings[] = {
+ {'\n', &newline_command},
{0, NULL}
};
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 1045fcb..50c441e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,6 +6,7 @@
*/
#include "shell.h"
+#include "key_functions.h"
#include
#include
#include
diff --git a/src/prompt.c b/src/prompt.c
index f91841a..656547b 100644
--- a/src/prompt.c
+++ b/src/prompt.c
@@ -29,11 +29,13 @@ int prompt_run(char *cmd, redirection *inout[2], env_t *env)
char **argv = get_argv(cmd);
if (!argv) {
- perror("mysh");
+ perror(SHELL_NAME);
return (-1);
}
if (!argv[0])
return (0);
+ if (inout[1] == NULL)
+ inout[1] = new_ncurses_pty();
if (**argv == '!' && argv[0][1] && argv[0][1] != ' ')
return (run_builtin(&builtins[5], argv, inout, env));
for (int i = 0; builtins[i].name; i++)
diff --git a/src/redirections/pty_pipe.c b/src/redirections/pty_pipe.c
new file mode 100644
index 0000000..b413d02
--- /dev/null
+++ b/src/redirections/pty_pipe.c
@@ -0,0 +1,91 @@
+/*
+** EPITECH PROJECT, 2020
+** ash
+** File description:
+** pty_pipe
+*/
+
+#include "redirections.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#define _XOPEN_SOURCE 600
+#define __USE_XOPEN_EXTENDED
+#include
+
+
+const struct redirection_map pty_type = {
+ .key = NULL,
+ .get_fd = &pyt_get_fd,
+ .run_cmd = &pty_get_output,
+ .type = OUTPUT | PIPE | EX_PIPE | PTY
+};
+
+int pty_open(char **slave_name)
+{
+ int master = open("/dev/ptmx", O_RDWR | O_NOCTTY);
+ int my_errno;
+
+ *slave_name = NULL;
+ if (master < 0)
+ return (-1);
+ if (grantpt(master) < 0 || unlockpt(master) < 0
+ || !(*slave_name = ptsname(master))) {
+ my_errno = errno;
+ close(master);
+ errno = my_errno;
+ return (-1);
+ }
+ return (master);
+}
+
+struct redirection *new_ncurses_pty()
+{
+ struct redirection *pty = malloc(sizeof(*pty));
+ char *slave;
+
+ if (!pty)
+ return (NULL);
+ pty->type = &pty_type;
+ pty->fd = -1;
+ pty->extra_data = pty_open(&slave);
+ if (pty->extra_data < 0) {
+ perror(SHELL_NAME);
+ return (pty);
+ }
+ pty->fd = open(slave, O_RDWR);
+ if (pty->fd == -1)
+ perror(SHELL_NAME);
+ return (pty);
+}
+
+// Function called only the child
+int pyt_get_fd(redirection *pty)
+{
+#ifdef TIOCSTTY
+ if (ioctl(pty->fd, TIOCSTTY, 0) == -1)
+ perror(SHELL_NAME);
+#endif
+ dup2(pty->fd, 2);
+ return (pty->fd);
+}
+
+// Function only called on the parent
+// READ FROM pty->extra_data and put it to the ncurses window;
+// Once the read return a EOF, the child program should be stopped.
+void pty_get_output(redirection *pty, env_t *env)
+{
+ char *line = NULL;
+ size_t size = 0;
+ FILE *file = fdopen(pty->extra_data, "r");
+ int y = getcury(env->window);
+
+ while (getline(&line, &size, file) > 0)
+ mvaddstr(y++, 0, line);
+ if (line)
+ free(line);
+}
\ No newline at end of file
diff --git a/src/redirections/redirections_functions.c b/src/redirections/redirections_functions.c
index 2680f1b..fd5b9e5 100644
--- a/src/redirections/redirections_functions.c
+++ b/src/redirections/redirections_functions.c
@@ -25,7 +25,7 @@ void redirection_ctr(redirection *red, char *cmd, const redirection_map *type)
red->fd = -1;
if (type->type & EX_PIPE) {
if (pipe(fd) != 0) {
- perror("mysh");
+ perror(SHELL_NAME);
red->fd = -1;
red->extra_data = -1;
return;
diff --git a/src/shell.c b/src/shell.c
index 225e066..10e3c02 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -15,31 +15,6 @@
#include
#include
-void test()
-{
- // char *cmd = NULL;
- // size_t read = 0;
- // char *p;
- // bool should_close = false;
-
- // while (!should_close) {
- // if (cmd) {
- // p = strchr(cmd, '\n');
- // if (p)
- // *p = '\0';
- // add_to_history(cmd, env);
- // if (eval_raw_cmd(cmd, env) < 0)
- // should_close = true;
- // }
- // if (!should_close) {
- // prompt_prepare(env);
- // should_close = getline(&cmd, &read, stdin) < 0;
- // }
- // }
- // if (cmd)
- // free(cmd);
-}
-
int process_key(int key, buffer_t *buffer, env_t *env)
{
for (int i = 0; env->bindings[i].func; i++)
@@ -48,23 +23,39 @@ int process_key(int key, buffer_t *buffer, env_t *env)
return (self_insert_command(key, buffer, env));
}
-void start_shell(env_t *env)
+WINDOW *window_create()
{
WINDOW *window = initscr();
- int key;
- buffer_t buffer = {.size = 0, .buffer = NULL, .pos = 0};
raw();
noecho();
keypad(window, true);
+ return (window);
+}
+
+void window_destroy(WINDOW *window)
+{
+ delwin(window);
+ noraw();
+ endwin();
+}
+
+void start_shell(env_t *env)
+{
+ buffer_t buffer = {.size = 0, .buffer = NULL, .pos = 0, .startx = 0};
+ int key;
+ int y;
+
+ env->window = window_create();
prompt_prepare(env);
do {
- printf("%s \n", buffer.buffer);
+ refresh();
+ y = getcury(env->window);
+ mvaddstr(y, buffer.startx, buffer.buffer);
+ move(y, buffer.pos + buffer.startx);
key = getch();
if (key == ERR)
break;
} while (process_key(key, &buffer, env) >= 0);
- delwin(window);
- noraw();
- endwin();
+ window_destroy(env->window);
}
\ No newline at end of file