fix history navigation bug and improve code by memalloc
This commit is contained in:
parent
a058bd3ae8
commit
5a67fcb3b5
5 changed files with 56 additions and 77 deletions
8
color.c
8
color.c
|
@ -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);
|
||||||
|
|
40
history.c
40
history.c
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
76
rush.c
76
rush.c
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < num_arg; i++) {
|
||||||
// makes ls and diff and grep have color without user typing it
|
// makes ls and diff and grep have color without user typing it
|
||||||
if (strncmp(args[0], "ls", 2) == 0 || strncmp(args[0], "diff", 4) == 0 || strncmp(args[0], "grep", 4) == 0) {
|
if (strncmp(args[i], "ls", 2) == 0 || strncmp(args[i], "diff", 4) == 0 || strncmp(args[i], "grep", 4) == 0) {
|
||||||
args[num_arg] = "--color=auto";
|
for (int j = num_arg; j > i; j--) {
|
||||||
|
args[j + 1] = args[j];
|
||||||
|
}
|
||||||
|
args[i + 1] = "--color=auto";
|
||||||
num_arg++;
|
num_arg++;
|
||||||
args[num_arg] = NULL;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
3
rush.h
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue