fix history navigation bug and improve code by memalloc

This commit is contained in:
Night Kaly 2024-02-10 17:29:58 +00:00
parent a058bd3ae8
commit 5a67fcb3b5
No known key found for this signature in database
GPG key ID: 8E829D3381CFEBBE
5 changed files with 56 additions and 77 deletions

View file

@ -2,6 +2,8 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "rush.h"
// color str in place // color str in place
void color_text(char str[], const char *color) { void color_text(char str[], const char *color) {
int size = snprintf(NULL, 0, "\x1b[38;2;%sm%s\x1b[0m", color, str) + 1; // calculate size that is needed for colored string int size = snprintf(NULL, 0, "\x1b[38;2;%sm%s\x1b[0m", color, str) + 1; // calculate size that is needed for colored string
@ -9,11 +11,7 @@ void color_text(char str[], const char *color) {
fprintf(stderr, "rush: snprintf failed\n"); fprintf(stderr, "rush: snprintf failed\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
char *buf = malloc(size); char *buf = memalloc(size);
if (buf == NULL) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
snprintf(buf, size, "\x1b[38;2;%sm%s\x1b[0m", color, str); // format string to buf snprintf(buf, size, "\x1b[38;2;%sm%s\x1b[0m", color, str); // format string to buf
strcpy(str, buf); strcpy(str, buf);

View file

@ -6,12 +6,21 @@
#include <linux/limits.h> #include <linux/limits.h>
#include "history.h" #include "history.h"
#include "rush.h"
#include "constants.h" #include "constants.h"
FILE *history_file; FILE *history_file;
char *histfile_path; char *histfile_path;
int cmd_count = 0; int cmd_count = 0;
FILE *open_history_file(char *mode) {
history_file = fopen(histfile_path, mode);
if (history_file == NULL) {
fprintf(stderr, "rush: Error opening history file\n");
exit(EXIT_FAILURE);
}
return history_file;
}
void check_history_file() { void check_history_file() {
char *env_home; char *env_home;
env_home = getenv("XDG_CONFIG_HOME"); env_home = getenv("XDG_CONFIG_HOME");
@ -26,11 +35,7 @@ void check_history_file() {
int env_home_len = strlen(env_home); int env_home_len = strlen(env_home);
int histfilename_len = strlen(HISTFILE); int histfilename_len = strlen(HISTFILE);
int path_len = env_home_len + histfilename_len + 2; // 2 for slash and null byte int path_len = env_home_len + histfilename_len + 2; // 2 for slash and null byte
histfile_path = malloc(sizeof(char) * path_len); histfile_path = memalloc(sizeof(char) * path_len);
if (histfile_path == NULL) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
histfile_path[0] = '\0'; // initialise string histfile_path[0] = '\0'; // initialise string
// concatenate home and history file name to a path // concatenate home and history file name to a path
strcat(histfile_path, env_home); strcat(histfile_path, env_home);
@ -38,21 +43,13 @@ void check_history_file() {
strcat(histfile_path, HISTFILE); strcat(histfile_path, HISTFILE);
histfile_path[path_len - 1] = '\0'; histfile_path[path_len - 1] = '\0';
if (access(histfile_path, F_OK) != 0) { // check for file existence if (access(histfile_path, F_OK) != 0) { // check for file existence
history_file = fopen(histfile_path, "w"); // read and write, if doesn't exist, create history_file = open_history_file("w"); // read and write, if doesn't exist, create
if (history_file == NULL) {
fprintf(stderr, "rush: Error opening history file\n");
exit(EXIT_FAILURE);
}
fclose(history_file); fclose(history_file);
} }
} }
void save_command_history(char *args) { void save_command_history(char *args) {
history_file = fopen(histfile_path, "a+"); history_file = open_history_file("a+");
if (history_file == NULL) {
fprintf(stderr, "rush: Error opening history file\n");
exit(EXIT_FAILURE);
}
char cmd[RL_BUFSIZE]; char cmd[RL_BUFSIZE];
cmd[0] = '\0'; cmd[0] = '\0';
strcat(cmd, args); strcat(cmd, args);
@ -97,17 +94,8 @@ int is_duplicate(char **history, int line_count, char *line) {
} }
char **get_all_history(bool check) { char **get_all_history(bool check) {
history_file = fopen(histfile_path, "r"); history_file = open_history_file("r");
if (history_file == NULL) { char **history = memalloc(MAX_HISTORY * sizeof(char*));
fprintf(stderr, "rush: Error opening history file\n");
exit(EXIT_FAILURE);
}
char **history = malloc(MAX_HISTORY * sizeof(char*));
if (history == NULL) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
char buffer[RL_BUFSIZE]; char buffer[RL_BUFSIZE];
int line_count = 0; int line_count = 0;

View file

@ -1,6 +1,8 @@
#ifndef HISTORY_H_ #ifndef HISTORY_H_
#define HISTORY_H_ #define HISTORY_H_
extern int cmd_count;
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);

80
rush.c
View file

@ -14,6 +14,15 @@
#include "history.h" #include "history.h"
#include "commands.h" #include "commands.h"
void *memalloc(size_t size) {
void *ptr = memalloc(size);
if (!ptr) {
fputs("rush: Error allocating memory\n", stderr);
exit(EXIT_FAILURE);
}
return ptr;
}
void quit_sig(int sig) { void quit_sig(int sig) {
exit(0); exit(0);
} }
@ -36,12 +45,8 @@ char **setup_path_variable() {
fprintf(stderr, "rush: PATH environment variable is missing\n"); fprintf(stderr, "rush: PATH environment variable is missing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
char *path_cpy = malloc(sizeof(char) * (strlen(envpath) + 1)); char *path_cpy = memalloc(sizeof(char) * (strlen(envpath) + 1));
char *path = malloc(sizeof(char) * (strlen(envpath) + 1)); char *path = memalloc(sizeof(char) * (strlen(envpath) + 1));
if (path_cpy == NULL || path == NULL) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
strcpy(path_cpy, envpath); strcpy(path_cpy, envpath);
strcpy(path, envpath); strcpy(path, envpath);
int path_count = 0; int path_count = 0;
@ -53,11 +58,7 @@ char **setup_path_variable() {
path_cpy++; path_cpy++;
} }
path_count += 2; // adding one to be correct and one for terminator path_count += 2; // adding one to be correct and one for terminator
char **paths = malloc(sizeof(char *) * path_count); char **paths = memalloc(sizeof(char *) * path_count);
if (paths == NULL) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
char *token = strtok(path, ":"); char *token = strtok(path, ":");
int counter = 0; int counter = 0;
while (token != NULL) { while (token != NULL) {
@ -110,12 +111,8 @@ void highlight(char *buffer, char **paths) {
if (cmd_part != NULL) { if (cmd_part != NULL) {
cmd_len = cmd_part - buffer; cmd_len = cmd_part - buffer;
char *cmd = malloc(sizeof(char) * (cmd_len + 1)); char *cmd = memalloc(sizeof(char) * (cmd_len + 1));
command_without_arg = malloc(sizeof(char) * (cmd_len + 1)); command_without_arg = memalloc(sizeof(char) * (cmd_len + 1));
if (cmd == NULL || command_without_arg == NULL) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < (cmd_part - buffer); i++) { for (int i = 0; i < (cmd_part - buffer); i++) {
cmd[i] = buffer[i]; cmd[i] = buffer[i];
} }
@ -151,17 +148,13 @@ void highlight(char *buffer, char **paths) {
char *readline(char **paths) { char *readline(char **paths) {
int bufsize = RL_BUFSIZE; int bufsize = RL_BUFSIZE;
int position = 0; int position = 0;
char *buffer = malloc(sizeof(char) * bufsize); char *buffer = memalloc(sizeof(char) * bufsize);
bool moved = false; bool moved = false;
bool backspaced = false; bool backspaced = false;
bool navigated = false; bool navigated = false;
bool insertatmiddle = false; bool insertatmiddle = false;
bool replaced = false; bool replaced = false;
if (!buffer) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
buffer[0] = '\0'; buffer[0] = '\0';
while (1) { while (1) {
@ -356,14 +349,9 @@ char *readline(char **paths) {
// split line into arguments // split line into arguments
char **argsplit(char *line) { char **argsplit(char *line) {
int bufsize = TOK_BUFSIZE, position = 0; int bufsize = TOK_BUFSIZE, position = 0;
char **tokens = malloc(bufsize * sizeof(char*)); char **tokens = memalloc(bufsize * sizeof(char*));
char *token; char *token;
if (!tokens) {
fprintf(stderr, "rush: Error allocating memory\n");
exit(EXIT_FAILURE);
}
token = strtok(line, TOK_DELIM); token = strtok(line, TOK_DELIM);
while (token != NULL) { while (token != NULL) {
tokens[position] = token; tokens[position] = token;
@ -387,14 +375,21 @@ char **argsplit(char *line) {
char **modifyargs(char **args) { char **modifyargs(char **args) {
int num_arg = 0; int num_arg = 0;
// check if command is ls, diff, or grep, if so, add --color=auto to the arguments
// this is to make ls, diff, and grep have color without user typing it
// this is to make the shell more user friendly
while (args[num_arg] != NULL) { while (args[num_arg] != NULL) {
num_arg++; num_arg++;
} }
// makes ls and diff and grep have color without user typing it for (int i = 0; i < num_arg; i++) {
if (strncmp(args[0], "ls", 2) == 0 || strncmp(args[0], "diff", 4) == 0 || strncmp(args[0], "grep", 4) == 0) { // makes ls and diff and grep have color without user typing it
args[num_arg] = "--color=auto"; if (strncmp(args[i], "ls", 2) == 0 || strncmp(args[i], "diff", 4) == 0 || strncmp(args[i], "grep", 4) == 0) {
num_arg++; for (int j = num_arg; j > i; j--) {
args[num_arg] = NULL; args[j + 1] = args[j];
}
args[i + 1] = "--color=auto";
num_arg++;
}
} }
return args; return args;
@ -414,16 +409,8 @@ char *trimws(char *str) {
} }
char ***pipe_argsplit(char *line) { char ***pipe_argsplit(char *line) {
char ***cmdv = malloc(sizeof(char **) * 128); // 127 commands, 1 for NULL char ***cmdv = memalloc(sizeof(char **) * 128); // 127 commands, 1 for NULL
if (cmdv == NULL) { char **cmds = memalloc(sizeof(char *) * 128); // 127 arguments, 1 for 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; int num_arg = 0;
char *pipe = strtok(line, "|"); char *pipe = strtok(line, "|");
while (pipe != NULL) { while (pipe != NULL) {
@ -437,6 +424,7 @@ char ***pipe_argsplit(char *line) {
for (int i = 0; i < num_arg; i++) { for (int i = 0; i < num_arg; i++) {
char **splitted = argsplit(cmds[i]); char **splitted = argsplit(cmds[i]);
cmdv[i] = modifyargs(splitted); cmdv[i] = modifyargs(splitted);
} }
cmdv[num_arg] = NULL; cmdv[num_arg] = NULL;
free(cmds); free(cmds);
@ -463,14 +451,14 @@ void command_loop(char **paths) {
char time[256]; char time[256];
strcpy(time, timestr); strcpy(time, timestr);
color_text(time, lavender); // lavender colored time string color_text(time, lavender); // lavender colored time string
char *cwd = malloc(sizeof(char) * (PATH_MAX + 2)); char *cwd = memalloc(sizeof(char) * (PATH_MAX + 2));
sprintf(cwd, "[%s]", cwdstr); sprintf(cwd, "[%s]", cwdstr);
color_text(cwd, pink); // pink colored current directory color_text(cwd, pink); // pink colored current directory
char arrow[32] = "»"; char arrow[32] = "»";
color_text(arrow, blue); color_text(arrow, blue);
printf("%s %s %s ", time, cwd, arrow); printf("%s %s %s ", time, cwd, arrow);
cmd_count = 0; // upward arrow key resets command count
line = readline(paths); line = readline(paths);
save_command_history(line); save_command_history(line);
bool has_pipe = false; bool has_pipe = false;
@ -490,7 +478,7 @@ void command_loop(char **paths) {
} else { } else {
args = argsplit(line); args = argsplit(line);
args = modifyargs(args); args = modifyargs(args);
status = execute(args); status = execute(args, STDOUT_FILENO, OPT_FGJ);
free(args); free(args);
} }
free(line); free(line);

3
rush.h
View file

@ -1,6 +1,9 @@
#ifndef RUSH_H_ #ifndef RUSH_H_
#define RUSH_H_ #define RUSH_H_
#include <stdio.h>
void *memalloc(size_t size);
char **argsplit(char *line); char **argsplit(char *line);
#endif #endif