Remove colors and und use default color, and use better codestyle
This commit is contained in:
parent
05f2a0e6e3
commit
1f0d5f5ea1
8 changed files with 521 additions and 523 deletions
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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);
|
||||||
|
|
885
src/90s.c
885
src/90s.c
|
@ -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
|
// check each character user has input
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case EOF:
|
case EOF:
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
case 10: {
|
case 10: {
|
||||||
// enter/new line feed
|
// enter/new line feed
|
||||||
if (buf_len == 0) {
|
if (buf_len == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// check if command includes !!
|
// check if command includes !!
|
||||||
if (strstr(buffer, "!!") != NULL) {
|
if (strstr(buffer, "!!") != NULL) {
|
||||||
char *last_command = read_command(1);
|
char *last_command = read_command(1);
|
||||||
if (last_command != NULL) {
|
if (last_command != NULL) {
|
||||||
// replace !! with the last command
|
// replace !! with the last command
|
||||||
char *replace = strstr(buffer, "!!");
|
char *replace = strstr(buffer, "!!");
|
||||||
int replace_len = strlen(replace);
|
int replace_len = strlen(replace);
|
||||||
int last_command_len = strlen(last_command);
|
int last_command_len = strlen(last_command);
|
||||||
int buffer_len = strlen(buffer);
|
int buffer_len = strlen(buffer);
|
||||||
if (last_command_len > replace_len) {
|
if (last_command_len > replace_len) {
|
||||||
buffer = realloc(buffer, buffer_len + last_command_len - replace_len + 1);
|
buffer = realloc(buffer, buffer_len + last_command_len - replace_len + 1);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
fprintf(stderr, "90s: Error allocating memory\n");
|
fprintf(stderr, "90s: Error allocating memory\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memmove(replace + last_command_len, replace + replace_len, buffer_len - (replace - buffer) - replace_len + 1);
|
memmove(replace + last_command_len, replace + replace_len, buffer_len - (replace - buffer) - replace_len + 1);
|
||||||
memcpy(replace, last_command, last_command_len);
|
memcpy(replace, last_command, last_command_len);
|
||||||
position += last_command_len - replace_len;
|
position += last_command_len - replace_len;
|
||||||
shiftright(last_command_len - replace_len);
|
shiftright(last_command_len - replace_len);
|
||||||
replaced = true;
|
replaced = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer[buf_len] = '\0';
|
buffer[buf_len] = '\0';
|
||||||
// clear all characters after the command
|
// clear all characters after the command
|
||||||
for (int start = buf_len + 1; buffer[start] != '\0'; start++) {
|
for (int start = buf_len + 1; buffer[start] != '\0'; start++) {
|
||||||
buffer[start] = '\0';
|
buffer[start] = '\0';
|
||||||
}
|
}
|
||||||
printf("\n"); // give space for response
|
printf("\n"); // give space for response
|
||||||
position = 0;
|
position = 0;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 127: // backspace
|
case 127: // backspace
|
||||||
if (buf_len >= 1) {
|
if (buf_len >= 1) {
|
||||||
position--;
|
position--;
|
||||||
for (int i = position; i < buf_len; i++) {
|
for (int i = position; i < buf_len; i++) {
|
||||||
// shift the buffer
|
// shift the buffer
|
||||||
buffer[i] = buffer[i + 1];
|
buffer[i] = buffer[i + 1];
|
||||||
}
|
}
|
||||||
backspaced = true;
|
backspaced = true;
|
||||||
moved = false;
|
moved = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 27: // arrow keys comes at three characters, 27, 91, then 65-68
|
case 27: // arrow keys comes at three characters, 27, 91, then 65-68
|
||||||
if (getchar() == 91) {
|
if (getchar() == 91) {
|
||||||
int arrow_key = getchar();
|
int arrow_key = getchar();
|
||||||
if (arrow_key == 65) { // up
|
if (arrow_key == 65) { // up
|
||||||
// read history file and fill prompt with latest command
|
// read history file and fill prompt with latest command
|
||||||
char *last_command = read_command(1);
|
char *last_command = read_command(1);
|
||||||
if (last_command != NULL) {
|
if (last_command != NULL) {
|
||||||
strcpy(buffer, last_command);
|
strcpy(buffer, last_command);
|
||||||
}
|
}
|
||||||
navigated = true;
|
navigated = true;
|
||||||
moved = false;
|
moved = false;
|
||||||
break;
|
break;
|
||||||
} else if (arrow_key == 66) { // down
|
} else if (arrow_key == 66) { // down
|
||||||
char *last_command = read_command(0);
|
char *last_command = read_command(0);
|
||||||
if (last_command != NULL) {
|
if (last_command != NULL) {
|
||||||
strcpy(buffer, last_command);
|
strcpy(buffer, last_command);
|
||||||
}
|
}
|
||||||
navigated = true;
|
navigated = true;
|
||||||
moved = false;
|
moved = false;
|
||||||
break;
|
break;
|
||||||
} else if (arrow_key == 67) { // right
|
} else if (arrow_key == 67) { // right
|
||||||
if (position < buf_len) {
|
if (position < buf_len) {
|
||||||
shiftright(1);
|
shiftright(1);
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
moved = true;
|
moved = true;
|
||||||
break;
|
break;
|
||||||
} else if (arrow_key == 68) { // left
|
} else if (arrow_key == 68) { // left
|
||||||
if (position >= 1) {
|
if (position >= 1) {
|
||||||
shiftleft(1);
|
shiftleft(1);
|
||||||
position--;
|
position--;
|
||||||
}
|
}
|
||||||
moved = true;
|
moved = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if (c > 31 && c < 127) {
|
if (c > 31 && c < 127) {
|
||||||
if (position == buf_len) {
|
if (position == buf_len) {
|
||||||
// Append character to the end of the buffer
|
// Append character to the end of the buffer
|
||||||
buffer[buf_len] = c;
|
buffer[buf_len] = c;
|
||||||
buffer[buf_len + 1] = '\0';
|
buffer[buf_len + 1] = '\0';
|
||||||
moved = false;
|
moved = false;
|
||||||
navigated = false;
|
navigated = false;
|
||||||
} else {
|
} else {
|
||||||
// Insert character at the current position
|
// Insert character at the current position
|
||||||
memmove(&buffer[position + 1], &buffer[position], buf_len - position + 1);
|
memmove(&buffer[position + 1], &buffer[position], buf_len - position + 1);
|
||||||
buffer[position] = c;
|
buffer[position] = c;
|
||||||
shiftright(1);
|
shiftright(1);
|
||||||
insertatmiddle = true;
|
insertatmiddle = true;
|
||||||
}
|
}
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_len = strlen(buffer);
|
buf_len = strlen(buffer);
|
||||||
|
|
||||||
if (replaced) {
|
if (replaced) {
|
||||||
shiftleft(buf_len);
|
shiftleft(buf_len);
|
||||||
clearline();
|
clearline();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (navigated && buf_len >= 1) {
|
if (navigated && buf_len >= 1) {
|
||||||
if (position > 0) {
|
if (position > 0) {
|
||||||
shiftleft(position); // move cursor to the beginning
|
shiftleft(position); // move cursor to the beginning
|
||||||
clearline();
|
clearline();
|
||||||
}
|
}
|
||||||
position = buf_len;
|
position = buf_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moved) {
|
if (moved) {
|
||||||
moved = false;
|
moved = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!navigated && !replaced) {
|
if (!navigated && !replaced) {
|
||||||
if (position != buf_len) {
|
if (position != buf_len) {
|
||||||
// not at normal place
|
// not at normal place
|
||||||
if (backspaced) {
|
if (backspaced) {
|
||||||
shiftleft(position + 1);
|
shiftleft(position + 1);
|
||||||
} else {
|
} else {
|
||||||
shiftleft(position); // move cursor to the beginning
|
shiftleft(position); // move cursor to the beginning
|
||||||
}
|
}
|
||||||
} else if (buf_len > 1) {
|
} else if (buf_len > 1) {
|
||||||
if (backspaced) {
|
if (backspaced) {
|
||||||
shiftleft(buf_len + 1); // move cursor to the beginning
|
shiftleft(buf_len + 1); // move cursor to the beginning
|
||||||
} else {
|
} else {
|
||||||
shiftleft(buf_len - 1); // move cursor to the beginning
|
shiftleft(buf_len - 1); // move cursor to the beginning
|
||||||
}
|
}
|
||||||
} else if (buf_len == 1) {
|
} else if (buf_len == 1) {
|
||||||
if (backspaced) {
|
if (backspaced) {
|
||||||
shiftleft(2);
|
shiftleft(2);
|
||||||
}
|
}
|
||||||
} else if (buf_len == 0) {
|
} else if (buf_len == 0) {
|
||||||
if (backspaced) {
|
if (backspaced) {
|
||||||
shiftleft(1);
|
shiftleft(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearline();
|
clearline();
|
||||||
} else {
|
} else {
|
||||||
navigated = false;
|
navigated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
highlight(buffer, paths);
|
highlight(buffer, paths);
|
||||||
|
|
||||||
if (backspaced) {
|
if (backspaced) {
|
||||||
if (buf_len != position) {
|
if (buf_len != position) {
|
||||||
shiftleft(buf_len - position);
|
shiftleft(buf_len - position);
|
||||||
}
|
}
|
||||||
backspaced = false;
|
backspaced = false;
|
||||||
}
|
}
|
||||||
if (insertatmiddle) {
|
if (insertatmiddle) {
|
||||||
shiftleft(buf_len - position); // move cursor back to where it was
|
shiftleft(buf_len - position); // move cursor back to where it was
|
||||||
insertatmiddle = false;
|
insertatmiddle = false;
|
||||||
}
|
}
|
||||||
if (replaced) {
|
if (replaced) {
|
||||||
replaced = false;
|
replaced = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have exceeded the buffer, reallocate.
|
// If we have exceeded the buffer, reallocate.
|
||||||
if ((buf_len + 1) >= bufsize) {
|
if ((buf_len + 1) >= bufsize) {
|
||||||
bufsize += RL_BUFSIZE;
|
bufsize += RL_BUFSIZE;
|
||||||
buffer = realloc(buffer, bufsize);
|
buffer = realloc(buffer, bufsize);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
fprintf(stderr, "90s: Error allocating memory\n");
|
fprintf(stderr, "90s: Error allocating memory\n");
|
||||||
exit(EXIT_FAILURE);
|
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;
|
||||||
}
|
}
|
||||||
|
|
18
src/color.c
18
src/color.c
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue