handle signals, rename functions, history command, qol features, fix highlight highlighting full command
This commit is contained in:
parent
28891a6ceb
commit
4c47f02034
9 changed files with 240 additions and 122 deletions
4
Makefile
4
Makefile
|
@ -1,4 +1,4 @@
|
||||||
rush: rush.c color.c constants.h history.c
|
rush: rush.c color.c constants.h history.c commands.c
|
||||||
gcc -o rush rush.c color.c history.c
|
gcc -o rush rush.c color.c history.c commands.c
|
||||||
all:
|
all:
|
||||||
rush
|
rush
|
||||||
|
|
|
@ -17,15 +17,15 @@ $ ./rush
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
- Showing current time and directory with custom color
|
- Showing current time and directory with custom color
|
||||||
- syntax highlighting on valid commands using ANSI colors
|
- Syntax highlighting on valid commands using ANSI colors
|
||||||
- history navigation using up and down keys
|
- History navigation using up and down keys with history command
|
||||||
|
- Built in commands
|
||||||
|
|
||||||
# Todo Features
|
# Todo Features
|
||||||
- Pipe
|
- Pipe
|
||||||
- stdin, stdout, stderr redirect
|
- stdin, stdout, stderr redirect
|
||||||
- background jobs
|
- background jobs
|
||||||
- editing using left and right arrow keys
|
- editing using left and right arrow keys
|
||||||
- history command
|
|
||||||
- export command to setenv
|
- export command to setenv
|
||||||
- tab completion
|
- tab completion
|
||||||
|
|
||||||
|
|
2
color.c
2
color.c
|
@ -11,7 +11,7 @@ void color_text(char str[], const char *color) {
|
||||||
}
|
}
|
||||||
char *buf = malloc(size);
|
char *buf = malloc(size);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
fprintf(stderr, "rush: Memory allocation failed\n");
|
fprintf(stderr, "rush: Error allocating memory\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
126
commands.c
Normal file
126
commands.c
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include "commands.h"
|
||||||
|
#include "history.h"
|
||||||
|
|
||||||
|
// Function declarations for builtin commands
|
||||||
|
int cd(char **args);
|
||||||
|
int help(char **args);
|
||||||
|
int quit(char **args);
|
||||||
|
int history(char **args);
|
||||||
|
|
||||||
|
// List of builtin commands' names
|
||||||
|
char *builtin_cmds[] = {
|
||||||
|
"cd",
|
||||||
|
"help",
|
||||||
|
"exit",
|
||||||
|
"history"
|
||||||
|
};
|
||||||
|
|
||||||
|
int (*builtin_func[]) (char **) = {
|
||||||
|
&cd,
|
||||||
|
&help,
|
||||||
|
&quit, // cant name it exit as it is taken
|
||||||
|
&history
|
||||||
|
};
|
||||||
|
|
||||||
|
// number of built in commands
|
||||||
|
int num_builtins() {
|
||||||
|
return sizeof(builtin_cmds) / sizeof(char *);
|
||||||
|
}
|
||||||
|
|
||||||
|
// change directory
|
||||||
|
int cd(char **args) {
|
||||||
|
if (args[1] == NULL) {
|
||||||
|
char *home = getenv("HOME");
|
||||||
|
if (chdir(home) != 0) {
|
||||||
|
perror("rush");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chdir(args[1]) != 0) {
|
||||||
|
perror("rush");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// show help menu
|
||||||
|
int help(char **args) {
|
||||||
|
printf("rush v0.01-alpha\n");
|
||||||
|
printf("Built in commands:\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < num_builtins(); i++) {
|
||||||
|
printf(" %s\n", builtin_cmds[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Use 'man' to read manual of programs\n");
|
||||||
|
printf("Licensed under GPL v3\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int quit(char **args) {
|
||||||
|
return 0; // exit prompting loop, which also the shell
|
||||||
|
}
|
||||||
|
|
||||||
|
int history(char **args) {
|
||||||
|
char **history = get_all_history();
|
||||||
|
|
||||||
|
for (int i = 0; history[i] != NULL; ++i) {
|
||||||
|
printf("%s\n", history[i]);
|
||||||
|
free(history[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(history);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_builtin(char *command) {
|
||||||
|
for (int i = 0; i < num_builtins(); i++) {
|
||||||
|
if (strcmp(command, builtin_cmds[i]) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute built in commands or launch commands and wait it to terminate, return 1 to keep shell running
|
||||||
|
int execute(char **args) {
|
||||||
|
if (args[0] == NULL) { // An empty command was entered.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_builtins(); i++) {
|
||||||
|
if (strcmp(args[0], builtin_cmds[i]) == 0) {
|
||||||
|
return (*builtin_func[i])(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid, wpid;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
// Child process
|
||||||
|
if (execvp(args[0], args) == -1) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
fprintf(stderr, "rush: command not found: %s\n", args[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (pid < 0) {
|
||||||
|
perror("Cannot fork");
|
||||||
|
} else {
|
||||||
|
// Parent process
|
||||||
|
do {
|
||||||
|
wpid = waitpid(pid, &status, WUNTRACED);
|
||||||
|
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
8
commands.h
Normal file
8
commands.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef COMMANDS_H_
|
||||||
|
#define COMMANDS_H_
|
||||||
|
|
||||||
|
int num_builtins();
|
||||||
|
bool is_builtin(char *command);
|
||||||
|
int execute(char **args);
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#define HISTFILE ".rush_history" // history file name
|
#define HISTFILE ".rush_history" // history file name
|
||||||
#define TOK_BUFSIZE 64 // buffer size of each token
|
#define TOK_BUFSIZE 64 // buffer size of each token
|
||||||
#define RL_BUFSIZE 1024
|
#define RL_BUFSIZE 1024 // size of each command
|
||||||
#define TOK_DELIM " \t\r\n\a" // delimiter for token
|
#define TOK_DELIM " \t\r\n\a" // delimiter for token
|
||||||
|
#define MAX_HISTORY 8192 // maximum lines of reading history
|
||||||
#endif
|
#endif
|
||||||
|
|
46
history.c
46
history.c
|
@ -2,6 +2,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
|
||||||
|
@ -89,3 +90,48 @@ char *read_command(int direction) {
|
||||||
fclose(history_file);
|
fclose(history_file);
|
||||||
return last_nlf + 1; // return the string from the new line feed
|
return last_nlf + 1; // return the string from the new line feed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_duplicate(char **history, int line_count, char *line) {
|
||||||
|
for (int i = 0; i < line_count; ++i) {
|
||||||
|
if (strcmp(history[i], line) == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char **get_all_history() {
|
||||||
|
history_file = fopen(histfile_path, "r");
|
||||||
|
if (history_file == NULL) {
|
||||||
|
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]; // Adjust the buffer size as needed
|
||||||
|
int line_count = 0;
|
||||||
|
|
||||||
|
while (fgets(buffer, sizeof(buffer), history_file) != NULL) {
|
||||||
|
buffer[strcspn(buffer, "\n")] = '\0';
|
||||||
|
if (!is_duplicate(history, line_count, buffer)) {
|
||||||
|
history[line_count] = strdup(buffer);
|
||||||
|
if (history[line_count] == NULL) {
|
||||||
|
fprintf(stderr, "Error allocating memory\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
line_count++;
|
||||||
|
if (line_count >= MAX_HISTORY) {
|
||||||
|
fprintf(stderr, "Maximum number of lines reached.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(history_file);
|
||||||
|
history[line_count] = NULL;
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
void save_command_history(char *command);
|
void save_command_history(char *command);
|
||||||
void check_history_file();
|
void check_history_file();
|
||||||
char *read_command(int direction);
|
char *read_command(int direction);
|
||||||
|
char **get_all_history();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
165
rush.c
165
rush.c
|
@ -1,4 +1,3 @@
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -7,112 +6,14 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
/*
|
void quit_sig(int sig) {
|
||||||
* Function Declarations for builtin shell commands:
|
return 0;
|
||||||
*/
|
|
||||||
int rush_cd(char **args);
|
|
||||||
int help(char **args);
|
|
||||||
int rush_exit(char **args);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List of builtin commands, followed by their corresponding functions.
|
|
||||||
*/
|
|
||||||
char *builtin_str[] = {
|
|
||||||
"cd",
|
|
||||||
"help",
|
|
||||||
"exit"
|
|
||||||
};
|
|
||||||
|
|
||||||
int (*builtin_func[]) (char **) = {
|
|
||||||
&rush_cd,
|
|
||||||
&help,
|
|
||||||
&rush_exit
|
|
||||||
};
|
|
||||||
|
|
||||||
int rush_num_builtins() {
|
|
||||||
return sizeof(builtin_str) / sizeof(char *);
|
|
||||||
}
|
|
||||||
|
|
||||||
// change directory
|
|
||||||
int rush_cd(char **args) {
|
|
||||||
if (args[1] == NULL) {
|
|
||||||
char *home = getenv("HOME");
|
|
||||||
if (chdir(home) != 0) {
|
|
||||||
perror("rush");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chdir(args[1]) != 0) {
|
|
||||||
perror("rush");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// show help menu
|
|
||||||
int help(char **args) {
|
|
||||||
printf("rush v0.01-alpha\n");
|
|
||||||
printf("Built in commands:\n");
|
|
||||||
|
|
||||||
for (int i = 0; i < rush_num_builtins(); i++) {
|
|
||||||
printf(" %s\n", builtin_str[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Use 'man' to read manual of programs\n");
|
|
||||||
printf("Licensed under GPL v3\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rush_exit(char **args) {
|
|
||||||
return 0; // exit prompting loop, which also the shell
|
|
||||||
}
|
|
||||||
|
|
||||||
// launch program and wait it to terminate, return 1 to continue running
|
|
||||||
int rush_launch(char **args) {
|
|
||||||
pid_t pid, wpid;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
// Child process
|
|
||||||
if (execvp(args[0], args) == -1) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
fprintf(stderr, "rush: command not found: %s\n", args[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else if (pid < 0) {
|
|
||||||
perror("Cannot fork");
|
|
||||||
} else {
|
|
||||||
// Parent process
|
|
||||||
do {
|
|
||||||
wpid = waitpid(pid, &status, WUNTRACED);
|
|
||||||
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// execute built in commands or launch commands, return 1 to keep shell running
|
|
||||||
int rush_execute(char **args) {
|
|
||||||
if (args[0] == NULL) {
|
|
||||||
// An empty command was entered.
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < rush_num_builtins(); i++) {
|
|
||||||
if (strcmp(args[0], builtin_str[i]) == 0) {
|
|
||||||
return (*builtin_func[i])(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rush_launch(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void change_terminal_attribute(int option) {
|
void change_terminal_attribute(int option) {
|
||||||
|
@ -165,20 +66,24 @@ bool find_command(char **paths, char *command) {
|
||||||
if (access(current_path, X_OK) == 0) {
|
if (access(current_path, X_OK) == 0) {
|
||||||
// command is executable
|
// command is executable
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
if (is_builtin(command)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
paths++;
|
paths++;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *rush_read_line(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 = malloc(sizeof(char) * bufsize);
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
fprintf(stderr, "rush: allocation error\n");
|
fprintf(stderr, "rush: Error allocating memory\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +91,7 @@ char *rush_read_line(char **paths) {
|
||||||
while (1) {
|
while (1) {
|
||||||
c = getchar(); // read a character
|
c = getchar(); // read a character
|
||||||
int buf_len = strlen(buffer);
|
int buf_len = strlen(buffer);
|
||||||
|
//printf("buflen %i\n", buf_len);
|
||||||
if (buf_len > 0) {
|
if (buf_len > 0) {
|
||||||
printf("\033[%dD", strlen(buffer)); // move cursor to the beginning
|
printf("\033[%dD", strlen(buffer)); // move cursor to the beginning
|
||||||
printf("\033[K"); // clear line to the right of cursor
|
printf("\033[K"); // clear line to the right of cursor
|
||||||
|
@ -240,21 +146,45 @@ char *rush_read_line(char **paths) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char *cmd_part = strchr(buffer, ' ');
|
char *cmd_part = strchr(buffer, ' ');
|
||||||
|
char *command_without_arg = NULL;
|
||||||
|
int cmd_len = 0;
|
||||||
bool valid;
|
bool valid;
|
||||||
|
|
||||||
if (cmd_part != NULL) {
|
if (cmd_part != NULL) {
|
||||||
char *cmd = malloc(sizeof(char) * (cmd_part - buffer + 1));
|
cmd_len = cmd_part - buffer;
|
||||||
|
char *cmd = malloc(sizeof(char) * cmd_len + 1);
|
||||||
|
command_without_arg = malloc(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];
|
||||||
}
|
}
|
||||||
cmd[cmd_part - buffer] = '\0';
|
strcpy(command_without_arg, cmd);
|
||||||
|
cmd[cmd_len] = '\0';
|
||||||
|
command_without_arg[cmd_len] = '\0';
|
||||||
valid = find_command(paths, cmd);
|
valid = find_command(paths, cmd);
|
||||||
} else {
|
} else {
|
||||||
valid = find_command(paths, buffer);
|
valid = find_command(paths, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
printf("\x1b[38;2;000;255;000m%s\x1b[0m", buffer); // print green as valid command
|
if (command_without_arg != NULL) {
|
||||||
|
buffer += cmd_len;
|
||||||
|
printf("\x1b[38;2;137;180;250m%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
|
||||||
|
buffer -= cmd_len;
|
||||||
} else {
|
} else {
|
||||||
printf("\x1b[38;2;255;000;000m%s\x1b[0m", buffer); // print red as sinvalid command
|
printf("\x1b[38;2;137;180;250m%s\x1b[0m", buffer); // print green as valid command
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (command_without_arg != NULL) {
|
||||||
|
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 green as valid command, but only color the command, not the arguments
|
||||||
|
buffer -= cmd_len;
|
||||||
|
} else {
|
||||||
|
printf("\x1b[38;2;243;139;168m%s\x1b[0m", buffer); // print red as sinvalid command
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
|
@ -263,7 +193,7 @@ char *rush_read_line(char **paths) {
|
||||||
bufsize += RL_BUFSIZE;
|
bufsize += RL_BUFSIZE;
|
||||||
buffer = realloc(buffer, bufsize);
|
buffer = realloc(buffer, bufsize);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
fprintf(stderr, "rush: allocation error\n");
|
fprintf(stderr, "rush: Error allocating memory\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +201,7 @@ char *rush_read_line(char **paths) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// split line into arguments
|
// split line into arguments
|
||||||
char **rush_split_line(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 = malloc(bufsize * sizeof(char*));
|
||||||
char *token;
|
char *token;
|
||||||
|
@ -297,6 +227,11 @@ char **rush_split_line(char *line) {
|
||||||
|
|
||||||
token = strtok(NULL, TOK_DELIM);
|
token = strtok(NULL, TOK_DELIM);
|
||||||
}
|
}
|
||||||
|
// makes ls and diff have color without user typing it
|
||||||
|
if (strcmp(tokens[0], "ls") == 0 || strcmp(tokens[0], "diff") == 0) {
|
||||||
|
tokens[position] = "--color=auto";
|
||||||
|
}
|
||||||
|
position++;
|
||||||
tokens[position] = NULL;
|
tokens[position] = NULL;
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
@ -329,9 +264,9 @@ void command_loop(char **paths) {
|
||||||
printf("%s %s %s ", time, cwd, arrow);
|
printf("%s %s %s ", time, cwd, arrow);
|
||||||
|
|
||||||
|
|
||||||
line = rush_read_line(paths);
|
line = readline(paths);
|
||||||
args = rush_split_line(line);
|
args = argsplit(line);
|
||||||
status = rush_execute(args);
|
status = execute(args);
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
free(args);
|
free(args);
|
||||||
|
@ -339,9 +274,11 @@ void command_loop(char **paths) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
// setup
|
// setup
|
||||||
|
signal(SIGINT, quit_sig);
|
||||||
|
signal(SIGTERM, quit_sig);
|
||||||
|
signal(SIGQUIT, quit_sig);
|
||||||
check_history_file();
|
check_history_file();
|
||||||
char **paths = setup_path_variable();
|
char **paths = setup_path_variable();
|
||||||
change_terminal_attribute(1); // turn off echoing and disabling getchar requires pressing enter key to return
|
change_terminal_attribute(1); // turn off echoing and disabling getchar requires pressing enter key to return
|
||||||
|
|
Loading…
Reference in a new issue