This commit is contained in:
Night Kaly 2024-02-09 01:18:14 +00:00
parent a6b28e5120
commit 3780d162ac
No known key found for this signature in database
GPG key ID: 8E829D3381CFEBBE
6 changed files with 123 additions and 18 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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);

75
rush.c
View file

@ -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);
args = argsplit(line); save_command_history(line);
args = modifyargs(args); bool has_pipe = false;
status = execute(args); 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 = modifyargs(args);
status = execute(args);
free(args);
}
free(line); free(line);
free(args);
free(cwd); free(cwd);
}; };
} }