Skip to content

Commit d2f9999

Browse files
committed
added command substitution
1 parent 65fd0e6 commit d2f9999

File tree

5 files changed

+99
-28
lines changed

5 files changed

+99
-28
lines changed

user/terminal/argv_tools.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include <argv_tools.h>
2+
#include <commands.h>
3+
24

35
#include <stdbool.h>
46
#include <stddef.h>
57
#include <string.h>
68
#include <stdlib.h>
9+
#include <stdio.h>
710

811
int get_command_type(char* command, int* token_pos, bool* double_pipe_symbol) {
912
*double_pipe_symbol = false;
@@ -66,22 +69,23 @@ char* read_env(char* in) {
6669

6770
i++;
6871

69-
while (((in[i] >= 'a' && in[i] <= 'z') || (in[i] >= 'A' && in[i] <= 'Z') || (in[i] >= '0' && in[i] <= '9') || (in[i] == '_' || in[i] == '?')) && in[i] != 0) {
70-
env_var[env_var_idx] = in[i];
71-
env_var_idx++;
72-
i++;
72+
while (((in[i] >= 'a' && in[i] <= 'z') || (in[i] >= 'A' && in[i] <= 'Z') || (in[i] >= '0' && in[i] <= '9') || (in[i] == '_' || in[i] == '?')) && in[i] != 0) {
73+
env_var[env_var_idx] = in[i];
74+
env_var_idx++;
75+
i++;
7376
}
7477

75-
// printf("env_var: %s\n", env_var);
78+
// printf("env_var: %s\n", env_var);
7679
char* env_var_value = getenv(env_var);
77-
// printf("env_var_value: %s\n", env_var_value);
80+
// printf("env_var_value: %s\n", env_var_value);
7881

7982
if (env_var_value != NULL) {
80-
strcat(tmp, env_var_value);
81-
tmp_idx += strlen(env_var_value);
82-
}
83+
strcat(tmp, env_var_value);
84+
tmp_idx += strlen(env_var_value);
85+
}
8386

84-
i--;
87+
i--;
88+
8589
} else {
8690
tmp[tmp_idx] = in[i];
8791
tmp_idx++;
@@ -243,4 +247,4 @@ char* process_line(char* command, bool check_hashtag) {
243247
}
244248

245249
return output_2;
246-
}
250+
}

user/terminal/commands.c

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,16 @@
1515
#include <buildin/path.h>
1616

1717
#define GET_CWD(cwd) char cwd[64] = { 0 }; set_env(SYS_GET_PWD_ID, cwd)
18-
#define PIPE_BUFFER_SIZE 65536
1918

20-
static pipe_t* make_pipe(char* buffer, int size, int pos) {
19+
pipe_t* make_pipe(char* buffer, int size, int pos) {
2120
pipe_t* p = malloc(sizeof(pipe_t));
2221
p->buffer = buffer;
2322
p->size = size;
2423
p->pos = pos;
2524
return p;
2625
}
2726

28-
bool command_received(char* command, bool* should_break, pipe_t* stdin_pipe) {
27+
bool command_received(char* command, bool* should_break, pipe_t* stdin_pipe, pipe_t* stdout_final_pipe) {
2928
*should_break = false;
3029

3130
int token_pos = 0;
@@ -37,7 +36,7 @@ bool command_received(char* command, bool* should_break, pipe_t* stdin_pipe) {
3736
pipe_t* command_stdin = stdin_pipe;
3837

3938
if (cmd_type == NORMAL) { //Normal command, just run it and send the stdin
40-
int found_command = run_command(command, terminal_envp, should_break, command_stdin, NULL);
39+
int found_command = run_command(command, terminal_envp, should_break, command_stdin, &stdout_final_pipe);
4140
if (!found_command) {
4241
printf("Error: Command not found: '%s'\n", command);
4342
}
@@ -101,7 +100,7 @@ bool command_received(char* command, bool* should_break, pipe_t* stdin_pipe) {
101100
stdout_pipe->size = stdout_pipe->pos;
102101
stdout_pipe->pos = 0;
103102
}
104-
found_command = command_received(next_command, should_break, stdout_pipe);
103+
found_command = command_received(next_command, should_break, stdout_pipe, stdout_final_pipe);
105104
}
106105

107106
if (stdout_pipe != NULL) { //Make sure to free the stdout if it was allocated
@@ -147,12 +146,72 @@ static int pipe_printf(pipe_t* out, const char *fmt, ...) {
147146
return printed;
148147
}
149148

150-
bool command_received(char* command, bool* should_break, pipe_t* stdin_pipe);
151149
void system_command_handler(char* in) {
152150
bool should_break = false;
153-
command_received(in, &should_break, NULL);
151+
command_received(in, &should_break, NULL, NULL);
154152
}
155153

154+
void append_char(char** result, int* result_capacity, int* result_len, char c) {
155+
if (*result_len + 1 >= *result_capacity) {
156+
*result_capacity *= 2;
157+
*result = realloc(*result, *result_capacity);
158+
}
159+
(*result)[(*result_len)++] = c;
160+
(*result)[*result_len] = '\0';
161+
}
162+
163+
char* execute_command_substitutions(char* command) {
164+
char* result = malloc(512);
165+
int result_capacity = 512;
166+
int result_len = 0;
167+
168+
while (*command) {
169+
char* substitution = malloc(65);
170+
int substitution_capacity = 64;
171+
int substitution_len = 0;
172+
173+
if (command[0] == '$' && command[1] == '(') {
174+
command += 2; // Skip past '$('
175+
176+
char prev = '(';
177+
while (*command != ')' || prev == '\\') {
178+
prev = *command++;
179+
if (prev == '\\') {
180+
continue;
181+
}
182+
183+
append_char(&substitution, &substitution_capacity, &substitution_len, prev);
184+
}
185+
186+
187+
bool should_break;
188+
pipe_t* stdout_final_pipe = make_pipe(malloc(PIPE_BUFFER_SIZE), PIPE_BUFFER_SIZE, 0);
189+
command_received(substitution, &should_break, NULL, stdout_final_pipe);
190+
191+
for (int j = 0; j < stdout_final_pipe->pos; j++) {
192+
append_char(&result, &result_capacity, &result_len, stdout_final_pipe->buffer[j]);
193+
}
194+
195+
free(stdout_final_pipe->buffer);
196+
free(stdout_final_pipe);
197+
198+
free(substitution);
199+
200+
command++; // Skip past ')'
201+
202+
if (result_len > 0 && result[result_len - 1] == '\n') {
203+
result[result_len - 1] = '\0';
204+
result_len--;
205+
}
206+
} else {
207+
append_char(&result, &result_capacity, &result_len, *command++);
208+
}
209+
}
210+
211+
return result;
212+
}
213+
214+
156215
bool run_command(char* command, char** terminal_envp, bool* should_break, pipe_t* stdin_pipe, pipe_t** stdout_pipe) {
157216
pipe_t* outgoing_stdout = stdout_pipe ? *stdout_pipe : NULL;
158217
pipe_t* incoming_stdin = stdin_pipe;
@@ -170,8 +229,10 @@ bool run_command(char* command, char** terminal_envp, bool* should_break, pipe_t
170229
} else if (strncmp(command, (char*)"pwd", 3) == 0) {
171230
pwd(outgoing_stdout);
172231
} else if (strncmp(command, (char*)"export ", 7) == 0) {
173-
char* argv_str = read_env(command);
232+
char* new_command = execute_command_substitutions(command);
233+
char* argv_str = read_env(new_command);
174234
export(argv_str, outgoing_stdout);
235+
free(new_command);
175236
free(argv_str);
176237
} else if (strncmp(command, (char*)"fault ", 6) == 0) {
177238
char* argv_str = read_env(command);
@@ -182,15 +243,18 @@ bool run_command(char* command, char** terminal_envp, bool* should_break, pipe_t
182243
} else if (strcmp(command, (char*)"exit") == 0) {
183244
*should_break = true;
184245
} else {
185-
char** argv = argv_split(command);
246+
char* new_command = execute_command_substitutions(command);
247+
char** argv = argv_split(new_command);
186248
argv = argv_env_process(argv);
187249

188250
int pid = spawn_process(argv, terminal_envp, outgoing_stdout, incoming_stdin);
189251
if (pid == -1) {
252+
free(new_command);
190253
free_argv(argv);
191254
return false;
192255
}
193256

257+
free(new_command);
194258
free_argv(argv);
195259
}
196260

@@ -401,7 +465,7 @@ int spawn_process(char** argv, char** terminal_envp, pipe_t* stdout, pipe_t* std
401465
char out[0x1000] = { 0 };
402466
if (ipc_message_ready(IPC_CONNECTION_TERMINAL, (void*) out)) {
403467
bool should_break = false;
404-
command_received(out, &should_break, NULL);
468+
command_received(out, &should_break, NULL, NULL);
405469
ipc_ok(IPC_CONNECTION_TERMINAL);
406470
}
407471
set_wait_and_yield();
@@ -417,4 +481,4 @@ int spawn_process(char** argv, char** terminal_envp, pipe_t* stdout, pipe_t* std
417481
done:
418482
free(executable);
419483
return pid;
420-
}
484+
}

user/terminal/include/commands.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
#include <stdbool.h>
44
#include <sys/spawn.h>
55

6+
#define PIPE_BUFFER_SIZE 65536
67

78
extern char** terminal_envp;
89

9-
bool command_received(char* command, bool* should_break, pipe_t* stdin_pipe);
10+
bool command_received(char* command, bool* should_break, pipe_t* stdin_pipe, pipe_t* stdout_final_pipe);
1011

1112
bool run_command(char* command, char** terminal_envp, bool* should_break, pipe_t* stdin_pipe, pipe_t** stdout_pipe);
1213

@@ -17,4 +18,6 @@ void export(char* command, pipe_t* out);
1718
void read_(char* command, pipe_t* out);
1819
void fault(char* command, pipe_t* out);
1920

20-
int spawn_process(char** argv, char** terminal_envp, pipe_t* stdout, pipe_t* stdin);
21+
pipe_t* make_pipe(char* buffer, int size, int pos);
22+
23+
int spawn_process(char** argv, char** terminal_envp, pipe_t* stdout, pipe_t* stdin);

user/terminal/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ int main(int argc, char* argv[], char* envp[]) {
180180
append_to_history(buffer);
181181

182182
bool should_break;
183-
command_received(buffer, &should_break, NULL); //This should block while command is running.
183+
command_received(buffer, &should_break, NULL, NULL); //This should block while command is running.
184184
if (should_break) {
185185
break;
186186
}
@@ -205,4 +205,4 @@ int main(int argc, char* argv[], char* envp[]) {
205205

206206
printf("\n[TERMINAL PROCESS ENDED]\n");
207207
return 0;
208-
}
208+
}

user/terminal/script.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void run_script(char* path, char** argv, int argc) {
8282
memcpy(command, processed_line, strlen(processed_line) + 1);
8383

8484
bool should_break;
85-
bool command_found = command_received(command, &should_break, NULL); //This should block while command is running.
85+
bool command_found = command_received(command, &should_break, NULL, NULL); //This should block while command is running.
8686
if (!command_found) {
8787
printf("Error: Command not found: '%s', line %d\n", command, line_number);
8888
exit(-1);
@@ -97,4 +97,4 @@ void run_script(char* path, char** argv, int argc) {
9797
fclose(file); // we still use the file object in the loop so we can only close it here.
9898
free(script_data);
9999
return;
100-
}
100+
}

0 commit comments

Comments
 (0)