Remove colors and und use default color, and use better codestyle

This commit is contained in:
Night Kaly 2024-11-12 22:54:49 +00:00
parent 05f2a0e6e3
commit 1f0d5f5ea1
Signed by: night0721
SSH key fingerprint: SHA256:B/hgVwUoBpx5vdNsXl9w8XwZljA9766uk6T4ubZp5HM
8 changed files with 521 additions and 523 deletions

View file

@ -1,5 +1,7 @@
#ifndef RUSH_H_ #ifndef S_H_
#define RUSH_H_ #define S_H_
#define VERSION "1.0.0"
#include <stdio.h> #include <stdio.h>

View file

@ -1,10 +0,0 @@
#ifndef COLOR_H_
#define COLOR_H_
const char *lavender = "174;174;255";
const char *pink = "255;210;239";
const char *blue = "137;180;250";
char *color_text(char str[], const char *color);
#endif

View file

@ -1,7 +1,6 @@
#ifndef COMMANDS_H_ #ifndef COMMANDS_H_
#define COMMANDS_H_ #define COMMANDS_H_
char *replace_absolute_home(char *str);
int num_builtins(void); int num_builtins(void);
bool is_builtin(char *command); bool is_builtin(char *command);
int execute(char **args, int fd, int options); int execute(char **args, int fd, int options);

887
src/90s.c
View file

@ -9,507 +9,526 @@
#include <signal.h> #include <signal.h>
#include <ctype.h> #include <ctype.h>
#include "color.h"
#include "constants.h" #include "constants.h"
#include "history.h" #include "history.h"
#include "commands.h" #include "commands.h"
void *memalloc(size_t size) { void *memalloc(size_t size)
void *ptr = malloc(size); {
if (!ptr) { void *ptr = malloc(size);
fputs("90s: Error allocating memory\n", stderr); if (!ptr) {
exit(EXIT_FAILURE); fputs("90s: Error allocating memory\n", stderr);
} exit(EXIT_FAILURE);
return ptr; }
return ptr;
} }
void change_terminal_attribute(int option) { void change_terminal_attribute(int option)
static struct termios oldt, newt; {
tcgetattr(STDIN_FILENO, &oldt); static struct termios oldt, newt;
if (option) { tcgetattr(STDIN_FILENO, &oldt);
newt = oldt; if (option) {
newt.c_lflag &= ~(ICANON | ECHO); // allows getchar without pressing enter key and echoing the character twice newt = oldt;
tcsetattr(STDIN_FILENO, TCSANOW, &newt); // set settings to stdin newt.c_lflag &= ~(ICANON | ECHO); // allows getchar without pressing enter key and echoing the character twice
} else { tcsetattr(STDIN_FILENO, TCSANOW, &newt); // set settings to stdin
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // restore to old settings } else {
} tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // restore to old settings
}
} }
char **setup_path_variable(void) { char **setup_path_variable(void)
char *envpath = getenv("PATH"); {
if (envpath == NULL) { char *envpath = getenv("PATH");
fprintf(stderr, "90s: PATH environment variable is missing\n"); if (envpath == NULL) {
exit(EXIT_FAILURE); fprintf(stderr, "90s: PATH environment variable is missing\n");
} exit(EXIT_FAILURE);
char *path_cpy = memalloc(sizeof(char) * (strlen(envpath) + 1)); }
char *path = memalloc(sizeof(char) * (strlen(envpath) + 1)); char *path_cpy = memalloc(strlen(envpath) + 1);
strcpy(path_cpy, envpath); char *path = memalloc(strlen(envpath) + 1);
strcpy(path, envpath); strcpy(path_cpy, envpath);
int path_count = 0; strcpy(path, envpath);
while (*path_cpy != '\0') { int path_count = 0;
// count number of : to count number of elements while (*path_cpy != '\0') {
if (*path_cpy == ':') { // count number of : to count number of elements
path_count++; if (*path_cpy == ':') {
} path_count++;
path_cpy++; }
} path_cpy++;
path_count += 2; // adding one to be correct and one for terminator }
char **paths = memalloc(sizeof(char *) * path_count); path_count += 2; // adding one to be correct and one for terminator
char *token = strtok(path, ":"); char **paths = memalloc(sizeof(char *) * path_count);
int counter = 0; char *token = strtok(path, ":");
while (token != NULL) { int counter = 0;
paths[counter] = token; // set element to the pointer of start of path while (token != NULL) {
token = strtok(NULL, ":"); paths[counter] = token; // set element to the pointer of start of path
counter++; token = strtok(NULL, ":");
} counter++;
paths[counter] = NULL; }
return paths; paths[counter] = NULL;
return paths;
} }
bool find_command(char **paths, char *command) { bool find_command(char **paths, char *command)
if (strncmp(command, "", 1) == 0) { {
return false; if (strncmp(command, "", 1) == 0) {
} return false;
while (*paths != NULL) { }
char current_path[PATH_MAX]; while (*paths != NULL) {
current_path[0] = '\0'; char current_path[PATH_MAX];
sprintf(current_path, "%s/%s", *paths, command); current_path[0] = '\0';
if (access(current_path, X_OK) == 0) { sprintf(current_path, "%s/%s", *paths, command);
// command is executable if (access(current_path, X_OK) == 0) {
return true; // command is executable
} else { return true;
if (is_builtin(command)) { } else {
return true; if (is_builtin(command)) {
} return true;
} }
paths++; }
} paths++;
return false; }
return false;
} }
void shiftleft(int chars) { void shiftleft(int chars)
printf("\033[%dD", chars); {
printf("\033[%dD", chars);
} }
void shiftright(int chars) { void shiftright(int chars)
printf("\033[%dC", chars); {
printf("\033[%dC", chars);
} }
void clearline(void) { void clearline(void)
printf("\033[K"); // clear line to the right of cursor {
printf("\033[K"); // clear line to the right of cursor
} }
void highlight(char *buffer, char **paths) { void highlight(char *buffer, char **paths)
char *cmd_part = strchr(buffer, ' '); {
char *command_without_arg = NULL; char *cmd_part = strchr(buffer, ' ');
int cmd_len = 0; char *command_without_arg = NULL;
bool valid; int cmd_len = 0;
bool valid;
if (cmd_part != NULL) { if (cmd_part != NULL) {
cmd_len = cmd_part - buffer; cmd_len = cmd_part - buffer;
char *cmd = memalloc(sizeof(char) * (cmd_len + 1)); char *cmd = memalloc(cmd_len + 1);
command_without_arg = memalloc(sizeof(char) * (cmd_len + 1)); command_without_arg = memalloc(cmd_len + 1);
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];
} }
strcpy(command_without_arg, cmd); strcpy(command_without_arg, cmd);
cmd[cmd_len] = '\0'; cmd[cmd_len] = '\0';
command_without_arg[cmd_len] = '\0'; command_without_arg[cmd_len] = '\0';
valid = find_command(paths, cmd); valid = find_command(paths, cmd);
free(cmd); free(cmd);
} else { } else {
valid = find_command(paths, buffer); valid = find_command(paths, buffer);
} }
if (valid) { if (valid) {
if (command_without_arg != NULL) { if (command_without_arg != NULL) {
buffer += cmd_len; buffer += cmd_len;
printf("\x1b[38;2;166;227;161m%s\x1b[0m\x1b[38;2;255;255;255m%s\x1b[0m", command_without_arg, buffer); // print green as valid command, but only color the command, not the arguments printf("\x1b[32m%s\x1b[37m%s\x1b[m", command_without_arg, buffer); // print green as valid command, but only color the command, not the arguments
buffer -= cmd_len; buffer -= cmd_len;
} else { } else {
printf("\x1b[38;2;166;227;161m%s\x1b[0m", buffer); // print green as valid command printf("\x1b[32m%s\x1b[m", buffer); // print green as valid command
} }
} else { } else {
if (command_without_arg != NULL) { if (command_without_arg != NULL) {
buffer += cmd_len; buffer += cmd_len;
printf("\x1b[38;2;243;139;168m%s\x1b[0m\x1b[38;2;255;255;255m%s\x1b[0m", command_without_arg, buffer); // print red as invalid command, but only color the command, not the arguments printf("\x1b[31m%s\x1b[37m%s\x1b[m", command_without_arg, buffer); // print red as invalid command, but only color the command, not the arguments
buffer -= cmd_len; buffer -= cmd_len;
} else { } else {
printf("\x1b[38;2;243;139;168m%s\x1b[0m", buffer); // print red as invalid command printf("\x1b[31m%s\x1b[m", buffer); // print red as invalid command
} }
} }
fflush(stdout); fflush(stdout);
free(command_without_arg); free(command_without_arg);
} }
char *readline(char **paths) { char *readline(char **paths)
int bufsize = RL_BUFSIZE; {
int position = 0; int bufsize = RL_BUFSIZE;
char *buffer = memalloc(sizeof(char) * bufsize); int position = 0;
char *buffer = memalloc(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;
buffer[0] = '\0'; buffer[0] = '\0';
while (1) { while (1) {
int c = getchar(); // read a character int c = getchar(); // read a character
int buf_len = strlen(buffer); int buf_len = strlen(buffer);
// check each character user has input
switch (c) {
case EOF:
exit(EXIT_SUCCESS);
case 10: {
// enter/new line feed
if (buf_len == 0) {
return NULL;
}
// check if command includes !!
if (strstr(buffer, "!!") != NULL) {
char *last_command = read_command(1);
if (last_command != NULL) {
// replace !! with the last command
char *replace = strstr(buffer, "!!");
int replace_len = strlen(replace);
int last_command_len = strlen(last_command);
int buffer_len = strlen(buffer);
if (last_command_len > replace_len) {
buffer = realloc(buffer, buffer_len + last_command_len - replace_len + 1);
if (!buffer) {
fprintf(stderr, "90s: Error allocating memory\n");
exit(EXIT_FAILURE);
}
}
memmove(replace + last_command_len, replace + replace_len, buffer_len - (replace - buffer) - replace_len + 1);
memcpy(replace, last_command, last_command_len);
position += last_command_len - replace_len;
shiftright(last_command_len - replace_len);
replaced = true;
break;
}
} else {
buffer[buf_len] = '\0';
// clear all characters after the command
for (int start = buf_len + 1; buffer[start] != '\0'; start++) {
buffer[start] = '\0';
}
printf("\n"); // give space for response
position = 0;
return buffer;
}
}
case 127: // backspace
if (buf_len >= 1) {
position--;
for (int i = position; i < buf_len; i++) {
// shift the buffer
buffer[i] = buffer[i + 1];
}
backspaced = true;
moved = false;
}
break;
case 27: // arrow keys comes at three characters, 27, 91, then 65-68
if (getchar() == 91) {
int arrow_key = getchar();
if (arrow_key == 65) { // up
// read history file and fill prompt with latest command
char *last_command = read_command(1);
if (last_command != NULL) {
strcpy(buffer, last_command);
}
navigated = true;
moved = false;
break;
} else if (arrow_key == 66) { // down
char *last_command = read_command(0);
if (last_command != NULL) {
strcpy(buffer, last_command);
}
navigated = true;
moved = false;
break;
} else if (arrow_key == 67) { // right
if (position < buf_len) {
shiftright(1);
position++;
}
moved = true;
break;
} else if (arrow_key == 68) { // left
if (position >= 1) {
shiftleft(1);
position--;
}
moved = true;
break;
}
}
default:
if (c > 31 && c < 127) {
if (position == buf_len) {
// Append character to the end of the buffer
buffer[buf_len] = c;
buffer[buf_len + 1] = '\0';
moved = false;
navigated = false;
} else {
// Insert character at the current position
memmove(&buffer[position + 1], &buffer[position], buf_len - position + 1);
buffer[position] = c;
shiftright(1);
insertatmiddle = true;
}
position++;
}
}
buf_len = strlen(buffer); // check each character user has input
switch (c) {
case EOF:
exit(EXIT_SUCCESS);
case 10: {
// enter/new line feed
if (buf_len == 0) {
return NULL;
}
// check if command includes !!
if (strstr(buffer, "!!") != NULL) {
char *last_command = read_command(1);
if (last_command != NULL) {
// replace !! with the last command
char *replace = strstr(buffer, "!!");
int replace_len = strlen(replace);
int last_command_len = strlen(last_command);
int buffer_len = strlen(buffer);
if (last_command_len > replace_len) {
buffer = realloc(buffer, buffer_len + last_command_len - replace_len + 1);
if (!buffer) {
fprintf(stderr, "90s: Error allocating memory\n");
exit(EXIT_FAILURE);
}
}
memmove(replace + last_command_len, replace + replace_len, buffer_len - (replace - buffer) - replace_len + 1);
memcpy(replace, last_command, last_command_len);
position += last_command_len - replace_len;
shiftright(last_command_len - replace_len);
replaced = true;
break;
}
} else {
buffer[buf_len] = '\0';
// clear all characters after the command
for (int start = buf_len + 1; buffer[start] != '\0'; start++) {
buffer[start] = '\0';
}
printf("\n"); // give space for response
position = 0;
return buffer;
}
}
case 127: // backspace
if (buf_len >= 1) {
position--;
for (int i = position; i < buf_len; i++) {
// shift the buffer
buffer[i] = buffer[i + 1];
}
backspaced = true;
moved = false;
}
break;
case 27: // arrow keys comes at three characters, 27, 91, then 65-68
if (getchar() == 91) {
int arrow_key = getchar();
if (arrow_key == 65) { // up
// read history file and fill prompt with latest command
char *last_command = read_command(1);
if (last_command != NULL) {
strcpy(buffer, last_command);
}
navigated = true;
moved = false;
break;
} else if (arrow_key == 66) { // down
char *last_command = read_command(0);
if (last_command != NULL) {
strcpy(buffer, last_command);
}
navigated = true;
moved = false;
break;
} else if (arrow_key == 67) { // right
if (position < buf_len) {
shiftright(1);
position++;
}
moved = true;
break;
} else if (arrow_key == 68) { // left
if (position >= 1) {
shiftleft(1);
position--;
}
moved = true;
break;
}
}
default:
if (c > 31 && c < 127) {
if (position == buf_len) {
// Append character to the end of the buffer
buffer[buf_len] = c;
buffer[buf_len + 1] = '\0';
moved = false;
navigated = false;
} else {
// Insert character at the current position
memmove(&buffer[position + 1], &buffer[position], buf_len - position + 1);
buffer[position] = c;
shiftright(1);
insertatmiddle = true;
}
position++;
}
}
if (replaced) { buf_len = strlen(buffer);
shiftleft(buf_len);
clearline();
}
if (navigated && buf_len >= 1) { if (replaced) {
if (position > 0) { shiftleft(buf_len);
shiftleft(position); // move cursor to the beginning clearline();
clearline(); }
}
position = buf_len;
}
if (moved) { if (navigated && buf_len >= 1) {
moved = false; if (position > 0) {
continue; shiftleft(position); // move cursor to the beginning
} clearline();
}
position = buf_len;
}
if (!navigated && !replaced) { if (moved) {
if (position != buf_len) { moved = false;
// not at normal place continue;
if (backspaced) { }
shiftleft(position + 1);
} else {
shiftleft(position); // move cursor to the beginning
}
} else if (buf_len > 1) {
if (backspaced) {
shiftleft(buf_len + 1); // move cursor to the beginning
} else {
shiftleft(buf_len - 1); // move cursor to the beginning
}
} else if (buf_len == 1) {
if (backspaced) {
shiftleft(2);
}
} else if (buf_len == 0) {
if (backspaced) {
shiftleft(1);
}
}
clearline();
} else {
navigated = false;
}
highlight(buffer, paths); if (!navigated && !replaced) {
if (position != buf_len) {
// not at normal place
if (backspaced) {
shiftleft(position + 1);
} else {
shiftleft(position); // move cursor to the beginning
}
} else if (buf_len > 1) {
if (backspaced) {
shiftleft(buf_len + 1); // move cursor to the beginning
} else {
shiftleft(buf_len - 1); // move cursor to the beginning
}
} else if (buf_len == 1) {
if (backspaced) {
shiftleft(2);
}
} else if (buf_len == 0) {
if (backspaced) {
shiftleft(1);
}
}
clearline();
} else {
navigated = false;
}
if (backspaced) { highlight(buffer, paths);
if (buf_len != position) {
shiftleft(buf_len - position);
}
backspaced = false;
}
if (insertatmiddle) {
shiftleft(buf_len - position); // move cursor back to where it was
insertatmiddle = false;
}
if (replaced) {
replaced = false;
}
// If we have exceeded the buffer, reallocate. if (backspaced) {
if ((buf_len + 1) >= bufsize) { if (buf_len != position) {
bufsize += RL_BUFSIZE; shiftleft(buf_len - position);
buffer = realloc(buffer, bufsize); }
if (!buffer) { backspaced = false;
fprintf(stderr, "90s: Error allocating memory\n"); }
exit(EXIT_FAILURE); if (insertatmiddle) {
} shiftleft(buf_len - position); // move cursor back to where it was
} insertatmiddle = false;
} }
if (replaced) {
replaced = false;
}
// If we have exceeded the buffer, reallocate.
if ((buf_len + 1) >= bufsize) {
bufsize += RL_BUFSIZE;
buffer = realloc(buffer, bufsize);
if (!buffer) {
fprintf(stderr, "90s: Error allocating memory\n");
exit(EXIT_FAILURE);
}
}
}
} }
// split line into arguments // split line into arguments
char **argsplit(char *line) { char **argsplit(char *line)
int bufsize = TOK_BUFSIZE, position = 0; {
char **tokens = memalloc(bufsize * sizeof(char*)); int bufsize = TOK_BUFSIZE, position = 0;
char *token; char **tokens = memalloc(sizeof(char *) * bufsize);
char *token;
token = strtok(line, TOK_DELIM); token = strtok(line, TOK_DELIM);
while (token != NULL) { while (token != NULL) {
tokens[position] = token; tokens[position] = token;
position++; position++;
if (position >= bufsize) { if (position >= bufsize) {
bufsize += TOK_BUFSIZE; bufsize += TOK_BUFSIZE;
tokens = realloc(tokens, bufsize * sizeof(char*)); tokens = realloc(tokens, sizeof(char *) * bufsize);
if (!tokens) { if (!tokens) {
fprintf(stderr, "90s: Error allocating memory\n"); fprintf(stderr, "90s: Error allocating memory\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
token = strtok(NULL, TOK_DELIM); token = strtok(NULL, TOK_DELIM);
} }
tokens[position] = NULL; tokens[position] = NULL;
return tokens; return tokens;
} }
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 // 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 ls, diff, and grep have color without user typing it
// this is to make the shell more user friendly // 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++) { 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[i], "ls", 2) == 0 || strncmp(args[i], "diff", 4) == 0 || strncmp(args[i], "grep", 4) == 0) { if (strncmp(args[i], "ls", 2) == 0 || strncmp(args[i], "diff", 4) == 0 || strncmp(args[i], "grep", 4) == 0) {
for (int j = num_arg; j > i; j--) { for (int j = num_arg; j > i; j--) {
args[j + 1] = args[j]; args[j + 1] = args[j];
} }
args[i + 1] = "--color=auto"; args[i + 1] = "--color=auto";
num_arg++; num_arg++;
} }
} }
return args; return args;
} }
char *trimws(char *str) { char *trimws(char *str)
{
char *end; char *end;
while (isspace((unsigned char) *str)) while (isspace((unsigned char) *str))
str++; str++;
if(*str == 0) if(*str == 0)
return str; return str;
end = str + strlen(str) - 1; end = str + strlen(str) - 1;
while (end > str && isspace((unsigned char) *end)) while (end > str && isspace((unsigned char) *end))
end--; end--;
*(end+1) = 0; *(end+1) = 0;
return str; return str;
} }
char ***pipe_argsplit(char *line) { char ***pipe_argsplit(char *line)
char ***cmdv = memalloc(sizeof(char **) * 128); // 127 commands, 1 for NULL {
char **cmds = memalloc(sizeof(char *) * 128); // 127 arguments, 1 for NULL char ***cmdv = memalloc(sizeof(char **) * 128); // 127 commands, 1 for NULL
int num_arg = 0; char **cmds = memalloc(sizeof(char *) * 128); // 127 arguments, 1 for NULL
char *pipe = strtok(line, "|"); int num_arg = 0;
while (pipe != NULL) { char *pipe = strtok(line, "|");
pipe = trimws(pipe); while (pipe != NULL) {
cmds[num_arg] = strdup(pipe); pipe = trimws(pipe);
pipe = strtok(NULL, "|"); cmds[num_arg] = strdup(pipe);
num_arg++; pipe = strtok(NULL, "|");
} num_arg++;
cmds[num_arg] = NULL; }
cmds[num_arg] = NULL;
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);
return cmdv; 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 **args; char *line;
int status = 1; char **args;
int status = 1;
while (status) { while (status) {
time_t t = time(NULL); /* Get current time */
struct tm* current_time = localtime(&t); // get current time time_t t = time(NULL);
char timestr[256]; struct tm *current_time = localtime(&t);
char cwdstr[PATH_MAX]; char timestr[256];
if (strftime(timestr, sizeof(timestr), "[%H:%M:%S]", current_time) == 0) { // format time string /* Format time string */
return; if (strftime(timestr, sizeof(timestr), "[%H:%M:%S]", current_time) == 0) {
} return;
if (getcwd(cwdstr, sizeof(cwdstr)) == NULL) { // get current working directory }
return; char cwd[PATH_MAX];
} /* Get current working directory */
char time[256]; if (getcwd(cwd, PATH_MAX) == NULL) {
strcpy(time, timestr); return;
char *modtime = memalloc(sizeof(char) * 256); }
modtime = color_text(time, lavender); // lavender colored time string char *home = getenv("HOME");
char *cwd = memalloc(sizeof(char) * (PATH_MAX + 2)); size_t home_len = strlen(home);
sprintf(cwd, "[%s]", cwdstr);
cwd = replace_absolute_home(cwd); int i = 0, j = 0;
cwd = color_text(cwd, pink); // pink colored current directory /* Check if cwd starts with home */
char *arrow = memalloc(sizeof(char) * 32); if (home && strncmp(cwd, home, home_len) == 0) {
strcpy(arrow, "»"); cwd[j++] = '~';
arrow = color_text(arrow, blue); i += home_len;
printf("%s %s %s ", modtime, cwd, arrow); }
while (cwd[i] != '\0') {
cwd[j++] = cwd[i++];
}
cwd[j] = '\0';
/* Blue time string, pink time, teal arrow */
printf("\033[34m%s\033[m \033[35m[%s] \033[36m>\033[m ", timestr, cwd);
fflush(stdout); fflush(stdout);
cmd_count = 0; // upward arrow key resets command count cmd_count = 0; // upward arrow key resets command count
line = readline(paths); line = readline(paths);
if (line == NULL) { if (line == NULL) {
printf("\n"); printf("\n");
continue; continue;
} }
save_command_history(line); save_command_history(line);
bool has_pipe = false; bool has_pipe = false;
for (int i = 0; line[i] != '\0'; i++) { for (int i = 0; line[i] != '\0'; i++) {
if (line[i] == '|') { if (line[i] == '|') {
has_pipe = true; has_pipe = true;
break; break;
} }
} }
if (has_pipe) { if (has_pipe) {
char ***pipe_args = pipe_argsplit(line); char ***pipe_args = pipe_argsplit(line);
status = execute_pipe(pipe_args); status = execute_pipe(pipe_args);
while (*pipe_args != NULL) { while (*pipe_args != NULL) {
free(*pipe_args); free(*pipe_args);
pipe_args++; pipe_args++;
} }
} else { } else {
args = argsplit(line); args = argsplit(line);
args = modifyargs(args); args = modifyargs(args);
status = execute(args, STDOUT_FILENO, OPT_FGJ); status = execute(args, STDOUT_FILENO, OPT_FGJ);
free(args); free(args);
} }
free(line); free(line);
free(modtime); };
free(cwd);
free(arrow);
};
} }
void quit_sig(int sig) { void quit_sig(int sig)
exit(EXIT_SUCCESS); {
exit(EXIT_SUCCESS);
} }
int main(int argc, char **argv) { int main(int argc, char **argv)
// setup {
signal(SIGINT, quit_sig); // setup
signal(SIGTERM, quit_sig); signal(SIGINT, quit_sig);
signal(SIGQUIT, quit_sig); signal(SIGTERM, quit_sig);
check_history_file(); signal(SIGQUIT, quit_sig);
char **paths = setup_path_variable(); check_history_file();
change_terminal_attribute(1); // turn off echoing and disabling getchar requires pressing enter key to return char **paths = setup_path_variable();
change_terminal_attribute(1); // turn off echoing and disabling getchar requires pressing enter key to return
command_loop(paths); command_loop(paths);
// cleanup // cleanup
free(paths); free(paths);
change_terminal_attribute(0); // change back to default settings change_terminal_attribute(0); // change back to default settings
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -1,18 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "90s.h"
// color str in place
char *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
if (size < 0) {
fprintf(stderr, "90s: snprintf failed\n");
exit(EXIT_FAILURE);
}
char *buf = memalloc(size);
snprintf(buf, size, "\x1b[38;2;%sm%s\x1b[0m", color, str); // format string to buf
return buf;
}

View file

@ -13,7 +13,7 @@
int execute(char **args); int execute(char **args);
// Function declarations for builtin commands /* Builtin commands */
int cd(char **args); int cd(char **args);
int help(char **args); int help(char **args);
int quit(char **args); int quit(char **args);
@ -23,7 +23,6 @@ int source(char **args);
int j(char **args); int j(char **args);
int bg(char **args); int bg(char **args);
// List of builtin commands' names
char *builtin_cmds[] = { char *builtin_cmds[] = {
"cd", "cd",
"help", "help",
@ -38,7 +37,7 @@ char *builtin_cmds[] = {
int (*builtin_func[]) (char **) = { int (*builtin_func[]) (char **) = {
&cd, &cd,
&help, &help,
&quit, // cant name it exit as it is taken &quit, /* Can't name it exit as it is taken */
&history, &history,
&export, &export,
&source, &source,
@ -53,12 +52,13 @@ char *shortcut_dirs[] = {
}; };
char *shortcut_expand_dirs[] = { char *shortcut_expand_dirs[] = {
"~/.nky/Coding/C/90s", "~/.nky/git/90s",
"~/.local/bin", "~/.local/bin",
"/usr/local/bin", "/usr/local/bin",
}; };
char *gethome(void) { char *gethome(void)
{
char *home = getenv("HOME"); char *home = getenv("HOME");
if (home == NULL) { if (home == NULL) {
fprintf(stderr, "Error: HOME environment variable not set.\n"); fprintf(stderr, "Error: HOME environment variable not set.\n");
@ -67,14 +67,15 @@ char *gethome(void) {
return home; return home;
} }
char *replace_home_dir(char *str) { char *replace_home_dir(char *str)
{
char *home_path = gethome(); char *home_path = gethome();
int path_len = strlen(str); int path_len = strlen(str);
int home_len = strlen(home_path); int home_len = strlen(home_path);
// Allocate memory for the new path // Allocate memory for the new path
char* new_path = memalloc(sizeof(char) * (path_len + home_len + 1)); char* new_path = memalloc(path_len + home_len + 1);
int i = 0, j = 0; int i = 0, j = 0;
while (str[i] != '\0') { while (str[i] != '\0') {
@ -93,37 +94,14 @@ char *replace_home_dir(char *str) {
return new_path; return new_path;
} }
char *replace_absolute_home(char *str) {
char *home_path = gethome();
int path_len = strlen(str);
int home_len = strlen(home_path);
// Allocate memory for the new path
char* new_path = memalloc(sizeof(char) * (path_len - home_len + 2));
int i = 0, j = 0;
while (str[i] != '\0') {
if (strncmp(&str[i], home_path, home_len) == 0) {
// Copy HOME environment variable value
new_path[j++] = '~';
i += home_len;
} else {
new_path[j++] = str[i++];
}
}
new_path[j] = '\0';
return new_path;
}
// number of built in commands // number of built in commands
int num_builtins(void) { int num_builtins(void) {
return sizeof(builtin_cmds) / sizeof(char *); return sizeof(builtin_cmds) / sizeof(char *);
} }
// autojump // autojump
int j(char **args) { int j(char **args)
{
if (args[1] == NULL) { if (args[1] == NULL) {
fprintf(stderr, "90s: not enough arguments\n"); fprintf(stderr, "90s: not enough arguments\n");
return -1; return -1;
@ -143,7 +121,9 @@ int j(char **args) {
return 1; return 1;
} }
// change directory /*
* Change directory
*/
int cd(char **args) { int cd(char **args) {
int i = 0; int i = 0;
if (args[1] == NULL) { if (args[1] == NULL) {
@ -166,9 +146,12 @@ int cd(char **args) {
return 1; return 1;
} }
// show help menu /*
int help(char **args) { * Show help menu
printf("90s %f\n", VERSION); */
int help(char **args)
{
printf("90s %s\n", VERSION);
printf("Built in commands:\n"); printf("Built in commands:\n");
for (int i = 0; i < num_builtins(); i++) { for (int i = 0; i < num_builtins(); i++) {
@ -180,11 +163,14 @@ int help(char **args) {
return 1; return 1;
} }
int quit(char **args) { int quit(char **args)
return 0; // exit prompting loop, which also the shell {
/* Exit prompt loop */
return 0;
} }
int history(char **args) { int history(char **args)
{
char **history = get_all_history(true); char **history = get_all_history(true);
for (int i = 0; history[i] != NULL; ++i) { for (int i = 0; history[i] != NULL; ++i) {
@ -196,8 +182,10 @@ int history(char **args) {
return 1; return 1;
} }
int export(char **args) { int export(char **args)
args++; // skip the command {
/* Skip the command */
args++;
while (*args != NULL) { while (*args != NULL) {
char *variable = strtok(*args, "=\n"); char *variable = strtok(*args, "=\n");
char *value = strtok(NULL, "=\n"); char *value = strtok(NULL, "=\n");
@ -215,7 +203,8 @@ int export(char **args) {
return 1; return 1;
} }
int source(char **args) { int source(char **args)
{
if (args[1] == NULL) { if (args[1] == NULL) {
fprintf(stderr, "90s: not enough arguments\n"); fprintf(stderr, "90s: not enough arguments\n");
return -1; return -1;
@ -245,7 +234,8 @@ int source(char **args) {
return status; // Indicate success return status; // Indicate success
} }
int bg(char **args) { int bg(char **args)
{
if (args[1] == NULL) { if (args[1] == NULL) {
fprintf(stderr, "90s: not enough arguments\n"); fprintf(stderr, "90s: not enough arguments\n");
return -1; return -1;
@ -263,7 +253,9 @@ int bg(char **args) {
printf("Job %i: %s\n", job_index, search->command); printf("Job %i: %s\n", job_index, search->command);
return 1; return 1;
} }
bool is_builtin(char *command) {
bool is_builtin(char *command)
{
for (int i = 0; i < num_builtins(); i++) { for (int i = 0; i < num_builtins(); i++) {
if (strcmp(command, builtin_cmds[i]) == 0) { if (strcmp(command, builtin_cmds[i]) == 0) {
return true; return true;
@ -272,7 +264,8 @@ bool is_builtin(char *command) {
return false; return false;
} }
int launch(char **args, int fd, int options) { int launch(char **args, int fd, int options)
{
int is_bgj = (options & OPT_BGJ) ? 1 : 0; int is_bgj = (options & OPT_BGJ) ? 1 : 0;
int redirect_stdout = (options & OPT_STDOUT) ? 1 : 0; int redirect_stdout = (options & OPT_STDOUT) ? 1 : 0;
int redirect_stdin = (options & OPT_STDIN) ? 1 : 0; int redirect_stdin = (options & OPT_STDIN) ? 1 : 0;
@ -325,7 +318,8 @@ int launch(char **args, int fd, int options) {
return 1; return 1;
} }
// execute built in commands or launch commands and wait it to terminate, return 1 to keep shell running // execute built in commands or launch commands and wait it to terminate, return 1 to keep shell running
int execute(char **args) { int execute(char **args)
{
if (args[0] == NULL) { // An empty command was entered. if (args[0] == NULL) { // An empty command was entered.
return 1; return 1;
} }
@ -407,7 +401,8 @@ int execute(char **args) {
} }
// execute_pipe with as many pipes as needed // execute_pipe with as many pipes as needed
int execute_pipe(char ***args) { int execute_pipe(char ***args)
{
int pipefd[2]; int pipefd[2];
pid_t pid; pid_t pid;
int in = 0; int in = 0;

View file

@ -13,7 +13,8 @@ FILE *history_file;
char *histfile_path; char *histfile_path;
int cmd_count = 0; int cmd_count = 0;
FILE *open_history_file(char *mode) { FILE *open_history_file(char *mode)
{
history_file = fopen(histfile_path, mode); history_file = fopen(histfile_path, mode);
if (history_file == NULL) { if (history_file == NULL) {
fprintf(stderr, "90s: Error opening history file\n"); fprintf(stderr, "90s: Error opening history file\n");
@ -21,7 +22,9 @@ FILE *open_history_file(char *mode) {
} }
return history_file; return history_file;
} }
void check_history_file(void) {
void check_history_file(void)
{
char *env_home; char *env_home;
env_home = getenv("XDG_CONFIG_HOME"); env_home = getenv("XDG_CONFIG_HOME");
if (env_home == NULL) { if (env_home == NULL) {
@ -48,7 +51,8 @@ void check_history_file(void) {
} }
} }
void save_command_history(char *args) { void save_command_history(char *args)
{
history_file = open_history_file("a+"); history_file = open_history_file("a+");
char cmd[RL_BUFSIZE]; char cmd[RL_BUFSIZE];
cmd[0] = '\0'; cmd[0] = '\0';
@ -60,8 +64,10 @@ void save_command_history(char *args) {
fclose(history_file); fclose(history_file);
} }
char *read_command(int direction) { char *read_command(int direction)
if (direction == 1) { // up {
/* Up */
if (direction == 1) {
cmd_count++; cmd_count++;
} else { // down } else { // down
if (cmd_count == 0) { if (cmd_count == 0) {
@ -84,7 +90,8 @@ char *read_command(int direction) {
return history[num_history - cmd_count]; return history[num_history - cmd_count];
} }
int is_duplicate(char **history, int line_count, char *line) { int is_duplicate(char **history, int line_count, char *line)
{
for (int i = 0; i < line_count; ++i) { for (int i = 0; i < line_count; ++i) {
if (strcmp(history[i], line) == 0) { if (strcmp(history[i], line) == 0) {
return 1; return 1;
@ -93,9 +100,10 @@ int is_duplicate(char **history, int line_count, char *line) {
return 0; return 0;
} }
char **get_all_history(bool check) { char **get_all_history(bool check)
{
history_file = open_history_file("r"); history_file = open_history_file("r");
char **history = memalloc(MAX_HISTORY * sizeof(char*)); char **history = memalloc(MAX_HISTORY * sizeof(char *));
char buffer[RL_BUFSIZE]; char buffer[RL_BUFSIZE];
int line_count = 0; int line_count = 0;

View file

@ -13,7 +13,8 @@ typedef struct job {
job *jobs = NULL; job *jobs = NULL;
int num_jobs(void) { int num_jobs(void)
{
job *current = jobs; job *current = jobs;
int count = 0; int count = 0;
while (current != NULL) { while (current != NULL) {
@ -23,7 +24,8 @@ int num_jobs(void) {
return count; return count;
} }
int add_job(pid_t pid, char *command, bool status) { int add_job(pid_t pid, char *command, bool status)
{
job *current = jobs; job *current = jobs;
job *new_job = memalloc(sizeof(job)); job *new_job = memalloc(sizeof(job));
new_job->pid = pid; new_job->pid = pid;
@ -45,7 +47,8 @@ int add_job(pid_t pid, char *command, bool status) {
return index; return index;
} }
job *get_job(int index) { job *get_job(int index)
{
job *current = jobs; job *current = jobs;
if (index == 0) { if (index == 0) {
return current; return current;