Browse Source

WIP piping

master
alistair 5 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 @@ _
| |
_ _
``` ```
## 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);
int add_alias(State* state, char *name, char *substitution); int add_alias(State* state, char *name, char *substitution);
int del_alias(State *state, char *name); int del_alias(State *state, char *name);
int repl(State* state, FILE *input); 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 get_growing_array(size_t num_elements, size_t size_elem) {
GrowingArray arr; GrowingArray arr;
@ -199,14 +202,83 @@ void shutdown(State *state) {
exit(0); 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[]) { int check_builtins(State *state, int num_args, char *args[]) {
char *builtins[NUM_BUILTINS] = { char *builtins[NUM_BUILTINS] = {
"cd", "cd",
"alias", "alias",
"unalias" "unalias"
}; };
if (!strcmp(args[0], "cd")) {
if (!strcmp(args[0], "cd")) {
if (num_args == 1) { if (num_args == 1) {
chdir(getenv("HOME")); chdir(getenv("HOME"));
return ER_SUCCESS; return ER_SUCCESS;
@ -343,15 +415,12 @@ int check_aliases(State *state, char **substitution, char *name) {
return ER_FAILURE; return ER_FAILURE;
} }
int expand_command(State *state, int argc, char* argv[]) {
int run_command(State *state, int argc, char *argv[]) {
pid_t child;
if (argc == 0) { if (argc == 0) {
return ER_FAILURE; return ER_FAILURE;
} }
char *substitution;
char *substitution;
if (!check_aliases(state, &substitution, argv[0])) { if (!check_aliases(state, &substitution, argv[0])) {
strip_char(argv[0], ' '); strip_char(argv[0], ' ');
argv[0] = reallocarray(argv[0], strlen(substitution) + 1, sizeof(char)); argv[0] = reallocarray(argv[0], strlen(substitution) + 1, sizeof(char));
@ -362,25 +431,29 @@ int run_command(State *state, int argc, char *argv[]) {
join_string(&joined, argc, argv, " "); join_string(&joined, argc, argv, " ");
split_string(&new_argv, &len, joined, ' '); split_string(&new_argv, &len, joined, ' ');
//run_command(state, len, new_argv); run_command(state, len, new_argv);
execute(stdin, stdout, new_argv, &child);
waitpid(child, NULL, 0);
return ER_SUCCESS;
for (int i = 0 ; i < len; i ++) { for (int i = 0 ; i < len; i ++) {
free(new_argv[i]); free(new_argv[i]);
} }
free(new_argv); 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) { if (check_builtins(state, argc, argv) == ER_NOT_EXISTS) {
execute(stdin, stdout, argv, &child); execute(0,1, argv, &child);
waitpid(child, NULL, 0); waitpid(child, NULL, 0);
} }
return ER_SUCCESS; return ER_SUCCESS;
} }
/* read eval print loop until EOF */
int repl(State* state, FILE *input) { int repl(State* state, FILE *input) {
while (true) { while (true) {
char *line; char *line;
@ -398,7 +471,11 @@ int repl(State* state, FILE *input) {
split_string(&sep_string, &num_words, line, ' '); 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++) { for (int i = 0; i < num_words; i++) {
free(sep_string[i]); free(sep_string[i]);

4
run.c

@ -5,9 +5,7 @@
* *
* Returns true on success or 1 on failure. * Returns true on success or 1 on failure.
*/ */
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 in_FD = fileno(in);
int out_FD = fileno(out);
int err = fork(); int err = fork();

2
run.h

@ -8,7 +8,7 @@
#ifndef RUNH #ifndef RUNH
#define 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); int change_dir(char *dir);

Loading…
Cancel
Save