pipes
This commit is contained in:
parent
a6b28e5120
commit
3780d162ac
6 changed files with 123 additions and 18 deletions
|
@ -26,11 +26,10 @@ $ ./rush
|
||||||
- Showing current time and directory with custom color
|
- Showing current time and directory with custom color
|
||||||
- Syntax highlighting on valid commands using ANSI colors
|
- Syntax highlighting on valid commands using ANSI colors
|
||||||
- History navigation using up and down keys with history command
|
- History navigation using up and down keys with history command
|
||||||
- Built in commands
|
- Support for environment variables
|
||||||
- Export environment variable
|
|
||||||
- Source commands from a file
|
|
||||||
- Editing using left and right arrow keys
|
- Editing using left and right arrow keys
|
||||||
- !! to repeat last command
|
- !! to repeat last command
|
||||||
|
- Pipes
|
||||||
|
|
||||||
# Built in commands
|
# Built in commands
|
||||||
- cd
|
- cd
|
||||||
|
@ -41,7 +40,6 @@ $ ./rush
|
||||||
- source
|
- source
|
||||||
|
|
||||||
# Todo Features
|
# Todo Features
|
||||||
- splits commands based on pipes and whitespaces
|
|
||||||
- stdin, stdout, stderr redirect
|
- stdin, stdout, stderr redirect
|
||||||
- background jobs
|
- background jobs
|
||||||
- tab completion
|
- tab completion
|
||||||
|
|
50
commands.c
50
commands.c
|
@ -159,8 +159,6 @@ int execute(char **args) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
save_command_history(args); // save command to history file
|
|
||||||
|
|
||||||
// prioritize builtin commands
|
// prioritize builtin commands
|
||||||
for (int i = 0; i < num_builtins(); i++) {
|
for (int i = 0; i < num_builtins(); i++) {
|
||||||
if (strcmp(args[0], builtin_cmds[i]) == 0) {
|
if (strcmp(args[0], builtin_cmds[i]) == 0) {
|
||||||
|
@ -199,3 +197,51 @@ int execute(char **args) {
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// execute_pipe with as many pipes as needed
|
||||||
|
int execute_pipe(char ***args) {
|
||||||
|
int pipefd[2];
|
||||||
|
int status;
|
||||||
|
pid_t pid;
|
||||||
|
int i = 0;
|
||||||
|
int in = 0;
|
||||||
|
|
||||||
|
int num_pipes = 0;
|
||||||
|
while (args[num_pipes] != NULL) {
|
||||||
|
num_pipes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_pipes; i++) {
|
||||||
|
pipe(pipefd);
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
dup2(in, 0); // change input according to the old one
|
||||||
|
if (i < num_pipes - 1) {
|
||||||
|
dup2(pipefd[1], 1); // change output according to the new one
|
||||||
|
}
|
||||||
|
close(pipefd[0]);
|
||||||
|
execvp(args[i][0], args[i]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (pid < 0) {
|
||||||
|
perror("fork failed");
|
||||||
|
}
|
||||||
|
close(pipefd[1]);
|
||||||
|
in = pipefd[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
dup2(in, 0);
|
||||||
|
execvp(args[i][0], args[i]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (pid < 0) {
|
||||||
|
perror("fork failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
close(pipefd[0]);
|
||||||
|
close(pipefd[1]);
|
||||||
|
|
||||||
|
for (i = 0; i <= num_pipes; i++) {
|
||||||
|
wait(&status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
int num_builtins();
|
int num_builtins();
|
||||||
bool is_builtin(char *command);
|
bool is_builtin(char *command);
|
||||||
int execute(char **args);
|
int execute(char **args);
|
||||||
|
int execute_pipe(char ***args);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,7 +47,7 @@ void check_history_file() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_command_history(char **args) {
|
void save_command_history(char *args) {
|
||||||
history_file = fopen(histfile_path, "a+");
|
history_file = fopen(histfile_path, "a+");
|
||||||
if (history_file == NULL) {
|
if (history_file == NULL) {
|
||||||
fprintf(stderr, "rush: Error opening history file\n");
|
fprintf(stderr, "rush: Error opening history file\n");
|
||||||
|
@ -55,10 +55,7 @@ void save_command_history(char **args) {
|
||||||
}
|
}
|
||||||
char cmd[RL_BUFSIZE];
|
char cmd[RL_BUFSIZE];
|
||||||
cmd[0] = '\0';
|
cmd[0] = '\0';
|
||||||
for (int i = 0; args[i] != NULL; ++i) {
|
strcat(cmd, args);
|
||||||
strcat(cmd, args[i]);
|
|
||||||
strcat(cmd, " ");
|
|
||||||
}
|
|
||||||
int cmd_len = strlen(cmd);
|
int cmd_len = strlen(cmd);
|
||||||
cmd[cmd_len] = '\n'; // put new line feed to split commands
|
cmd[cmd_len] = '\n'; // put new line feed to split commands
|
||||||
// ptr to first obj, size of each obj, number of obj, file ptr
|
// ptr to first obj, size of each obj, number of obj, file ptr
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef HISTORY_H_
|
#ifndef HISTORY_H_
|
||||||
#define HISTORY_H_
|
#define HISTORY_H_
|
||||||
|
|
||||||
void save_command_history(char **args);
|
void save_command_history(char *args);
|
||||||
void check_history_file();
|
void check_history_file();
|
||||||
char *read_command(int direction);
|
char *read_command(int direction);
|
||||||
char **get_all_history(bool check);
|
char **get_all_history(bool check);
|
||||||
|
|
69
rush.c
69
rush.c
|
@ -7,6 +7,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
@ -386,8 +387,11 @@ char **argsplit(char *line) {
|
||||||
char **modifyargs(char **args) {
|
char **modifyargs(char **args) {
|
||||||
int num_arg = 0;
|
int num_arg = 0;
|
||||||
|
|
||||||
|
while (args[num_arg] != NULL) {
|
||||||
|
num_arg++;
|
||||||
|
}
|
||||||
// makes ls and diff have color without user typing it
|
// makes ls and diff have color without user typing it
|
||||||
if (strncmp(args[0], "ls", 2) == 0 || strncmp(args[0], "diff", 4) == 0) {
|
if (strncmp(args[0], "ls", 2) == 0 || strncmp(args[0], "diff", 4) == 0 || strncmp(args[0], "grep", 4) == 0) {
|
||||||
args[num_arg] = "--color=auto";
|
args[num_arg] = "--color=auto";
|
||||||
num_arg++;
|
num_arg++;
|
||||||
args[num_arg] = NULL;
|
args[num_arg] = NULL;
|
||||||
|
@ -396,6 +400,49 @@ char **modifyargs(char **args) {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *trimws(char *str) {
|
||||||
|
char *end;
|
||||||
|
while (isspace((unsigned char) *str))
|
||||||
|
str++;
|
||||||
|
if(*str == 0)
|
||||||
|
return str;
|
||||||
|
end = str + strlen(str) - 1;
|
||||||
|
while (end > str && isspace((unsigned char) *end))
|
||||||
|
end--;
|
||||||
|
*(end+1) = 0;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ***pipe_argsplit(char *line) {
|
||||||
|
char ***cmdv = malloc(sizeof(char **) * 128); // 127 commands, 1 for NULL
|
||||||
|
if (cmdv == NULL) {
|
||||||
|
fprintf(stderr, "rush: Error allocating memory\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
char **cmds = malloc(sizeof(char *) * 128); // 127 arguments, 1 for NULL
|
||||||
|
if (cmds == NULL) {
|
||||||
|
fprintf(stderr, "rush: Error allocating memory\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
int num_arg = 0;
|
||||||
|
char *pipe = strtok(line, "|");
|
||||||
|
while (pipe != NULL) {
|
||||||
|
pipe = trimws(pipe);
|
||||||
|
cmds[num_arg] = strdup(pipe);
|
||||||
|
pipe = strtok(NULL, "|");
|
||||||
|
num_arg++;
|
||||||
|
}
|
||||||
|
cmds[num_arg] = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_arg; i++) {
|
||||||
|
char **splitted = argsplit(cmds[i]);
|
||||||
|
cmdv[i] = modifyargs(splitted);
|
||||||
|
}
|
||||||
|
cmdv[num_arg] = NULL;
|
||||||
|
free(cmds);
|
||||||
|
return cmdv;
|
||||||
|
}
|
||||||
|
|
||||||
// continously prompt for command and execute it
|
// continously prompt for command and execute it
|
||||||
void command_loop(char **paths) {
|
void command_loop(char **paths) {
|
||||||
char *line;
|
char *line;
|
||||||
|
@ -425,12 +472,28 @@ void command_loop(char **paths) {
|
||||||
|
|
||||||
|
|
||||||
line = readline(paths);
|
line = readline(paths);
|
||||||
|
save_command_history(line);
|
||||||
|
bool has_pipe = false;
|
||||||
|
for (int i = 0; line[i] != '\0'; i++) {
|
||||||
|
if (line[i] == '|') {
|
||||||
|
has_pipe = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_pipe) {
|
||||||
|
char ***pipe_args = pipe_argsplit(line);
|
||||||
|
status = execute_pipe(pipe_args);
|
||||||
|
while (*pipe_args != NULL) {
|
||||||
|
free(*pipe_args);
|
||||||
|
pipe_args++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
args = argsplit(line);
|
args = argsplit(line);
|
||||||
args = modifyargs(args);
|
args = modifyargs(args);
|
||||||
status = execute(args);
|
status = execute(args);
|
||||||
|
|
||||||
free(line);
|
|
||||||
free(args);
|
free(args);
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
free(cwd);
|
free(cwd);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue