Browse Source

WIP piping

master
alistair 4 years ago
parent
commit
0d1b87e741
  1. 14
      README.md
  2. 105
      main.c
  3. 4
      run.c
  4. 2
      run.h

14
README.md

@ -15,3 +15,17 @@ _ @@ -15,3 +15,17 @@ _
|
_
```
## To-Do
1. Pipes
2. Exclude things inside quote marks from string splitting and substitutions
3. Interrupts ^C and ^Z, bg, fg
- & and &&, ;
4. Wildcard substitutions *, ? etc
5. tab completion, handling escape sequences like ^[[D
6. Functions and variables
7. PS1

105
main.c

@ -9,6 +9,9 @@ int get_alias(Alias *alias, State *state, char *name); @@ -9,6 +9,9 @@ int get_alias(Alias *alias, State *state, char *name);
int add_alias(State* state, char *name, char *substitution);
int del_alias(State *state, char *name);
int repl(State* state, FILE *input);
int run_command(State *state, int argc, char *argv[]);
int get_array_element(ArrayElement **ret, GrowingArray* array, char* key);
int del_array_element(GrowingArray* array, char* key);
GrowingArray get_growing_array(size_t num_elements, size_t size_elem) {
GrowingArray arr;
@ -199,14 +202,83 @@ void shutdown(State *state) { @@ -199,14 +202,83 @@ void shutdown(State *state) {
exit(0);
}
int check_pipes(State* state, int num_args, char* args[]) {
int left = 0;
int num_commands = 0;
int space = 10;
// an array of string-arrays which end in NULL
char** *pipes = calloc(space, sizeof(char***));
for (int i = 0; i < num_args; i++) {
if (!strcmp(args[i], "|") || i == num_args - 1) {
int command_length = i - left + 1 + num_commands;
char **command = calloc(command_length, sizeof(char**));
// copy the command into the array
for (int k = 0; k < command_length - 1; k++) {
command[k] = args[left + k];
}
command[command_length - 1] = 0;
// grow the array if needed
if (num_commands == space - 2) {
pipes = calloc((space *= 2), sizeof(char***));
}
pipes[num_commands] = command;
num_commands++;
left = i + 1;
}
}
if (num_commands == 1) {
return ER_NOT_EXISTS;
}
int pipein[2];
int pipeout[2];
memset(pipein, 0, sizeof(int) * 2);
memset(pipeout, 0, sizeof(int) * 2);
pipe(pipein);
pipe(pipeout);
// 0 is read, 1 is write
pid_t child;
int in;
int out;
in = 0;
out = pipeout[1];
for (int i = 0; i < num_commands; i++) {
execute(in, out, pipes[i], &child);
if (i != num_commands - 1) {
if (in == pipein[0]) {
in = pipeout[0];
out = pipein[1];
} else {
in = pipein[0];
out = pipeout[1];
}
} else {
out = 1;
in = out - 1;
}
}
return ER_SUCCESS;
}
int check_builtins(State *state, int num_args, char *args[]) {
char *builtins[NUM_BUILTINS] = {
"cd",
"alias",
"unalias"
};
if (!strcmp(args[0], "cd")) {
if (!strcmp(args[0], "cd")) {
if (num_args == 1) {
chdir(getenv("HOME"));
return ER_SUCCESS;
@ -343,15 +415,12 @@ int check_aliases(State *state, char **substitution, char *name) { @@ -343,15 +415,12 @@ int check_aliases(State *state, char **substitution, char *name) {
return ER_FAILURE;
}
int run_command(State *state, int argc, char *argv[]) {
pid_t child;
int expand_command(State *state, int argc, char* argv[]) {
if (argc == 0) {
return ER_FAILURE;
}
char *substitution;
char *substitution;
if (!check_aliases(state, &substitution, argv[0])) {
strip_char(argv[0], ' ');
argv[0] = reallocarray(argv[0], strlen(substitution) + 1, sizeof(char));
@ -362,25 +431,29 @@ int run_command(State *state, int argc, char *argv[]) { @@ -362,25 +431,29 @@ int run_command(State *state, int argc, char *argv[]) {
join_string(&joined, argc, argv, " ");
split_string(&new_argv, &len, joined, ' ');
//run_command(state, len, new_argv);
execute(stdin, stdout, new_argv, &child);
waitpid(child, NULL, 0);
return ER_SUCCESS;
run_command(state, len, new_argv);
for (int i = 0 ; i < len; i ++) {
free(new_argv[i]);
}
free(new_argv);
return ER_SUCCESS;
} else {
run_command(state, argc, argv);
}
return ER_SUCCESS;
}
int run_command(State *state, int argc, char *argv[]) {
pid_t child;
if (check_builtins(state, argc, argv) == ER_NOT_EXISTS) {
execute(stdin, stdout, argv, &child);
execute(0,1, argv, &child);
waitpid(child, NULL, 0);
}
return ER_SUCCESS;
}
/* read eval print loop until EOF */
int repl(State* state, FILE *input) {
while (true) {
char *line;
@ -398,7 +471,11 @@ int repl(State* state, FILE *input) { @@ -398,7 +471,11 @@ int repl(State* state, FILE *input) {
split_string(&sep_string, &num_words, line, ' ');
run_command(state, num_words, sep_string);
int err = check_pipes(state, num_words, sep_string);
if (err == ER_NOT_EXISTS) {
expand_command(state, num_words, sep_string);
}
for (int i = 0; i < num_words; i++) {
free(sep_string[i]);

4
run.c

@ -5,9 +5,7 @@ @@ -5,9 +5,7 @@
*
* Returns true on success or 1 on failure.
*/
int execute(FILE *in, FILE *out, char *args[], pid_t* child_ID) {
int in_FD = fileno(in);
int out_FD = fileno(out);
int execute(int in_FD, int out_FD, char *args[], pid_t* child_ID) {
int err = fork();

2
run.h

@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
#ifndef RUNH
#define RUNH
int execute(FILE *in, FILE *out, char *args[], pid_t* child_ID);
int execute(int in_FD, int out_FD, char *args[], pid_t* child_ID);
int change_dir(char *dir);

Loading…
Cancel
Save