-
Notifications
You must be signed in to change notification settings - Fork 0
/
shell.c
123 lines (117 loc) · 3.61 KB
/
shell.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
** EPITECH PROJECT, 2023
** shell.c
** File description:
** shell for 42sh
*/
#include "shell.h"
#include "history.h"
#include "prompt.h"
#include "line_edition.h"
void process_key(ShellContext *context, InputBuffer *input_data)
{
realloc_input(input_data);
if (input_data->read[0] == '\x1b' && input_data->read[1] == '[') {
if (process_arrow_keys(input_data, context)) return;
if (process_delete_key(input_data)) return;
if (process_home_end_keys(input_data)) return;
return;
} if (input_data->read[0] == 0x7f) {
process_backspace_key(input_data);
return;
} if (input_data->read[0] == 4) {
handle_ctrl_d(context);
return;
} if (input_data->read[0] == '\t') {
process_tab_key(input_data, context);
return;
} if (strchr(input_data->read, '\n'))
process_enter_key(context, input_data);
else
process_regular_key(input_data);
}
void write_prompt(envdata_t *env)
{
char *user = get_environment_variable(env->env, "USER");
char *host = get_environment_variable(env->env, "HOSTNAME");
if (env->is_fallback) {
printf("\033[0m\033[93;1;5m> \033[0m");
fflush(stdout);
return;
}
char *stat_icon = WIFSIGNALED(env->status) && env->status != 1 ? "⚡" :
(env->status ? "×" : "λ");
if (user && host)
printf(env->starship_prompt ? STDPROMPT : NNSTDPROMPT, user + 5,
host + 9, env->cwd, stat_icon);
if (user && !host)
printf(env->starship_prompt ? ONEVALPROMPT : NNOVPROMPT,
user + 5, env->cwd, stat_icon);
if (!user && host)
printf(env->starship_prompt ? ONEVALPROMPT : NNOVPROMPT, host + 9,
env->cwd, stat_icon);
fflush(stdout);
}
char *read_stdin(void)
{
size_t size = 1024, read;
char *buffer = malloc(size);
if (!buffer) return buffer;
size_t total = 0;
while ((read = fread(buffer + total, 1, size - total, stdin)) > 0) {
total += read;
if (total == size) {
size *= 2;
char *tmpbuf = realloc(buffer, size);
buffer = (tmpbuf) ? tmpbuf : buffer;
}
}
buffer[total] = '\0';
return buffer;
}
static void run_non_tty(ShellContext *context)
{
char* input = read_stdin();
char* end_line;
char* start_line = input;
if (!start_line) return;
while ((end_line = strchr(start_line, '\n')) != NULL) {
size_t len = end_line - start_line + 1;
char* commands = malloc(len + 1);
if (!commands) {
free(input);
return;
}
strncpy(commands, start_line, len);
commands[len] = '\0';
context->status = run_user_input(commands, context->env,
&context->exiting);
free(commands);
start_line = end_line + 1;
}
context->exiting = true;
free(input);
}
int shell(envdata_t *env, struct termios *old_term, struct termios *new_term)
{
ShellContext context = {env, 0, false};
InputBuffer input_data = {malloc(1024), NULL,0, 0, {0}, 0, 1,false};
memset(input_data.input, 0, 1024);
buffer_clearing(&context, &input_data);
if (isatty(0)) {
configure_terminal(new_term, old_term);
write_prompt(env);
input_data.is_tty = true;
} else {
run_non_tty(&context);
free(input_data.input);
return context.status;
}
while (!context.exiting) {
input_data.read_len = read(STDIN_FILENO, input_data.read, 4);
process_key(&context, &input_data);
fflush(stdout);
memset(input_data.read, 0, 5);
}
free(input_data.input); return context.status;
}