PatchworkOS
Loading...
Searching...
No Matches
interactive.c
Go to the documentation of this file.
1#include "interactive.h"
2#include "ansi.h"
3#include "history.h"
4#include "pipeline.h"
5
6#include <errno.h>
7#include <stdbool.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/io.h>
12#include <sys/kbd.h>
13#include <sys/proc.h>
14
15static void interactive_prompt(void)
16{
17 char cwd[MAX_PATH] = {0};
18 if (readfile("/proc/self/cwd", cwd, MAX_PATH - 1, 0) == ERR)
19 {
20 strcpy(cwd, "?");
21 }
22 printf("\n\033[32m%s\n\033[92m>\033[m ", cwd);
24}
25
34
36{
37 if (state->pos == 0)
38 {
39 return 0;
40 }
41
42 history_push(&state->history, state->buffer);
43
44 pipeline_t pipeline;
45 if (pipeline_init(&pipeline, state->buffer) == ERR)
46 {
47 return 0; // This is fine
48 }
49
50 if (pipeline_execute(&pipeline) == ERR)
51 {
52 pipeline_deinit(&pipeline);
53 return 0; // This is also fine
54 }
55
56 if (pipeline.status != 0)
57 {
58 printf("shell: command exited with status %d (%s)\n", pipeline.status, strerror(pipeline.status));
59 }
60 state->status = pipeline.status;
61 pipeline_deinit(&pipeline);
62 return 0;
63}
64
66{
67 if (result->type == ANSI_PRINTABLE)
68 {
69 if (state->pos >= MAX_PATH - 1)
70 {
71 return 0;
72 }
73 memmove(&state->buffer[state->pos + 1], &state->buffer[state->pos], MAX_PATH - state->pos - 1);
74 state->buffer[state->pos++] = result->printable;
75 printf("%c\033[s%s\033[u", result->printable, &state->buffer[state->pos]);
77 return 0;
78 }
79
80 switch (result->type)
81 {
82 case ANSI_BACKSPACE:
83 if (state->pos == 0)
84 {
85 break;
86 }
87 memmove(&state->buffer[state->pos - 1], &state->buffer[state->pos], MAX_PATH - state->pos + 1);
88 state->buffer[MAX_PATH - 1] = '\0';
89 state->pos--;
90 // Move left, save cursor, print rest of line, clear to end, restore cursor
91 printf("\033[1D\033[s%s\033[K\033[u", &state->buffer[state->pos]);
93 break;
94 case ANSI_NEWLINE:
95 printf("\n");
96 if (interactive_execute_command(state) == ERR)
97 {
98 return ERR;
99 }
100 memset(state->buffer, 0, MAX_PATH);
101 state->pos = 0;
103 break;
104 case ANSI_TAB:
105 // TODO: Ignore tabs for now
106 break;
107 case ANSI_ARROW_UP:
108 {
109 const char* previous = history_previous(&state->history);
110 if (previous == NULL)
111 {
112 break;
113 }
114 while (state->pos > 0) // Cant use \r because of prompt
115 {
116 state->pos--;
117 printf("\033[D");
118 }
119 strncpy(state->buffer, previous, MAX_PATH - 1);
120 state->buffer[MAX_PATH - 1] = '\0';
121 state->pos = strlen(state->buffer);
122 printf("\033[K%s", state->buffer);
123 fflush(stdout);
124 }
125 break;
126 case ANSI_ARROW_DOWN:
127 {
128 const char* next = history_next(&state->history);
129 while (state->pos > 0) // Cant use \r because of prompt
130 {
131 state->pos--;
132 printf("\033[D");
133 }
134 printf("\033[K");
135 if (next == NULL)
136 {
137 memset(state->buffer, 0, MAX_PATH);
138 state->pos = 0;
139 fflush(stdout);
140 break;
141 }
142 strncpy(state->buffer, next, MAX_PATH - 1);
143 state->buffer[MAX_PATH - 1] = '\0';
144 state->pos = strlen(state->buffer);
145 printf("%s", state->buffer);
146 fflush(stdout);
147 }
148 break;
149 case ANSI_ARROW_RIGHT:
150 if (state->pos < strlen(state->buffer))
151 {
152 state->pos++;
153 printf("\033[C");
154 fflush(stdout);
155 }
156 break;
157 case ANSI_ARROW_LEFT:
158 if (state->pos > 0)
159 {
160 state->pos--;
161 printf("\033[D");
162 fflush(stdout);
163 }
164 break;
165 case ANSI_HOME:
166 while (state->pos > 0)
167 {
168 state->pos--;
169 printf("\033[D");
170 }
171 fflush(stdout);
172 break;
173 case ANSI_END:
174 while (state->pos < strlen(state->buffer))
175 {
176 state->pos++;
177 printf("\033[C");
178 }
179 fflush(stdout);
180 break;
181 case ANSI_CTRL_C:
182 printf("^C\n");
183 memset(state->buffer, 0, MAX_PATH);
184 state->pos = 0;
186 break;
187 default:
188 break;
189 }
190
191 return 0;
192}
193
194static uint64_t interactive_handle_input(interactive_state_t* state, const char* input, uint64_t length)
195{
196 for (uint64_t i = 0; i < length; i++)
197 {
198 ansi_result_t result;
199 if (ansi_parse(&state->ansi, input[i], &result) == ERR)
200 {
201 printf("shell: failed to parse ansi sequence (%s)\n", strerror(errno));
202 continue;
203 }
204
205 if (result.type == ANSI_STILL_PARSING)
206 {
207 continue;
208 }
209
210 if (interactive_handle_ansi(state, &result) == ERR)
211 {
212 return ERR;
213 }
214 }
215
216 return 0;
217}
218
220{
221 printf("Welcome to the PatchworkOS Shell!\n");
222 printf("Type \033[92mhelp\033[m for information on how to use the shell.\n");
223
225
227 ansi_init(&state.ansi);
228 history_init(&state.history);
229 state.status = 0;
230 memset(state.buffer, 0, MAX_PATH);
231 state.pos = 0;
232
233 while (true)
234 {
235 char buffer[MAX_PATH];
237 if (readCount == ERR)
238 {
239 printf("shell: failed to read input (%s)\n", strerror(errno));
240 return EXIT_FAILURE;
241 }
242
243 if (interactive_handle_input(&state, buffer, readCount) == ERR)
244 {
245 history_deinit(&state.history);
246 return state.status;
247 }
248 }
249}
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
void ansi_init(ansi_t *ansi)
Definition ansi.c:6
uint64_t ansi_parse(ansi_t *ansi, char input, ansi_result_t *result)
Definition ansi.c:11
#define errno
Error number variable.
Definition errno.h:27
uint64_t readfile(const char *path, void *buffer, uint64_t count, uint64_t offset)
Wrapper for reading a file directly using a path.
Definition readfile.c:3
uint64_t read(fd_t fd, void *buffer, uint64_t count)
System call for reading from files.
Definition read.c:9
#define STDIN_FILENO
Definition io.h:44
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
const char * history_previous(history_t *history)
Definition history.c:60
void history_deinit(history_t *history)
Definition history.c:12
void history_push(history_t *history, const char *entry)
Definition history.c:20
void history_init(history_t *history)
Definition history.c:6
const char * history_next(history_t *history)
Definition history.c:48
static uint64_t interactive_handle_input(interactive_state_t *state, const char *input, uint64_t length)
static uint64_t interactive_handle_ansi(interactive_state_t *state, ansi_result_t *result)
Definition interactive.c:65
int interactive_shell(void)
static void interactive_prompt(void)
Definition interactive.c:15
static uint64_t interactive_execute_command(interactive_state_t *state)
Definition interactive.c:35
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
uint64_t pipeline_execute(pipeline_t *pipeline)
Definition pipeline.c:442
void pipeline_deinit(pipeline_t *pipeline)
Definition pipeline.c:275
uint64_t pipeline_init(pipeline_t *pipeline, const char *cmdline)
Definition pipeline.c:17
static atomic_long next
Definition main.c:10
@ ANSI_BACKSPACE
Definition ansi.h:20
@ ANSI_CTRL_C
Definition ansi.h:32
@ ANSI_HOME
Definition ansi.h:29
@ ANSI_ARROW_DOWN
Definition ansi.h:24
@ ANSI_NEWLINE
Definition ansi.h:21
@ ANSI_END
Definition ansi.h:30
@ ANSI_TAB
Definition ansi.h:22
@ ANSI_STILL_PARSING
Definition ansi.h:18
@ ANSI_PRINTABLE
Definition ansi.h:19
@ ANSI_ARROW_UP
Definition ansi.h:23
@ ANSI_ARROW_RIGHT
Definition ansi.h:26
@ ANSI_ARROW_LEFT
Definition ansi.h:25
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC int fflush(FILE *stream)
Definition fflush.c:6
_PUBLIC int printf(const char *_RESTRICT format,...)
Definition printf.c:5
FILE * stdout
Definition std_streams.c:17
#define EXIT_FAILURE
Definition stdlib.h:47
_PUBLIC char * strerror(int errnum)
Definition strerror.c:6
_PUBLIC void * memmove(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
_PUBLIC char * strncpy(char *_RESTRICT s1, const char *_RESTRICT s2, size_t n)
Definition strncpy.c:3
_PUBLIC size_t strlen(const char *s)
Definition strlen.c:3
_PUBLIC char * strcpy(char *_RESTRICT s1, const char *_RESTRICT s2)
Definition strcpy.c:3
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4
char printable
Definition ansi.h:38
ansi_result_type_t type
Definition ansi.h:37
Definition ansi.h:9
char buffer[MAX_PATH]
Definition interactive.c:31
int status
Definition pipeline.h:24