Swithced to 2 spaces indent
This commit is contained in:
parent
bd61469247
commit
1a4792f417
@ -7,17 +7,17 @@
|
||||
#include <string.h>
|
||||
|
||||
enum keys {
|
||||
DELETE_KEY = 1000,
|
||||
UP_KEY,
|
||||
DOWN_KEY,
|
||||
LEFT_KEY,
|
||||
RIGHT_KEY,
|
||||
HOME_KEY,
|
||||
END_KEY,
|
||||
BACKSPACE_KEY,
|
||||
ENTER_KEY,
|
||||
TAB_KEY,
|
||||
ESCAPE_KEY
|
||||
DELETE_KEY = 1000,
|
||||
UP_KEY,
|
||||
DOWN_KEY,
|
||||
LEFT_KEY,
|
||||
RIGHT_KEY,
|
||||
HOME_KEY,
|
||||
END_KEY,
|
||||
BACKSPACE_KEY,
|
||||
ENTER_KEY,
|
||||
TAB_KEY,
|
||||
ESCAPE_KEY
|
||||
};
|
||||
|
||||
void change_mode(int on);
|
||||
|
@ -25,60 +25,60 @@
|
||||
// Types definitions
|
||||
struct hist_sub
|
||||
{
|
||||
char **content;
|
||||
int length;
|
||||
int pos;
|
||||
char **content;
|
||||
int length;
|
||||
int pos;
|
||||
};
|
||||
|
||||
struct history
|
||||
{
|
||||
char **content;
|
||||
ssize_t length;
|
||||
int pos;
|
||||
FILE *file;
|
||||
char **content;
|
||||
ssize_t length;
|
||||
int pos;
|
||||
FILE *file;
|
||||
|
||||
struct hist_sub sub;
|
||||
struct hist_sub sub;
|
||||
};
|
||||
|
||||
struct status
|
||||
{
|
||||
int s;
|
||||
bool invert;
|
||||
int s;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_SEP,
|
||||
SEMICOLON_SEP,
|
||||
AND_SEP,
|
||||
OR_SEP
|
||||
NO_SEP,
|
||||
SEMICOLON_SEP,
|
||||
AND_SEP,
|
||||
OR_SEP
|
||||
} cmd_sep;
|
||||
|
||||
typedef struct pipes
|
||||
{
|
||||
char **args;
|
||||
ssize_t args_am;
|
||||
int pipefd[2];
|
||||
struct pipes *next;
|
||||
char **args;
|
||||
ssize_t args_am;
|
||||
int pipefd[2];
|
||||
struct pipes *next;
|
||||
} cmd_pipe;
|
||||
|
||||
typedef struct commands
|
||||
{
|
||||
cmd_pipe *pipe;
|
||||
ssize_t pipes_am;
|
||||
cmd_pipe *pipe;
|
||||
ssize_t pipes_am;
|
||||
|
||||
char **envs;
|
||||
ssize_t envs_am;
|
||||
char **envs;
|
||||
ssize_t envs_am;
|
||||
|
||||
struct status stat;
|
||||
struct commands *next;
|
||||
cmd_sep sep_next;
|
||||
struct status stat;
|
||||
struct commands *next;
|
||||
cmd_sep sep_next;
|
||||
} cmds_p;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct history hist;
|
||||
int last_status;
|
||||
struct history hist;
|
||||
int last_status;
|
||||
} t_;
|
||||
|
||||
//Globals defenition
|
||||
|
@ -8,9 +8,9 @@
|
||||
|
||||
struct tree_node
|
||||
{
|
||||
struct tree_node *child[ALPHABET_SIZE];
|
||||
struct tree_node *child[ALPHABET_SIZE];
|
||||
|
||||
int is_leaf;
|
||||
int is_leaf;
|
||||
};
|
||||
|
||||
struct tree_node *get_new_node();
|
||||
|
274
src/complete.c
274
src/complete.c
@ -13,16 +13,16 @@
|
||||
*/
|
||||
bool check_if_executable(char *path, char *file_name)
|
||||
{
|
||||
char *file_path = malloc(strlen(path) + strlen(file_name) + 2);
|
||||
file_path[0] = '\0';
|
||||
file_path = strcat(file_path, path);
|
||||
file_path = strcat(file_path, "/");
|
||||
file_path = strcat(file_path, file_name);
|
||||
char *file_path = malloc(strlen(path) + strlen(file_name) + 2);
|
||||
file_path[0] = '\0';
|
||||
file_path = strcat(file_path, path);
|
||||
file_path = strcat(file_path, "/");
|
||||
file_path = strcat(file_path, file_name);
|
||||
|
||||
bool ret = access(file_path, X_OK) == 0;
|
||||
free(file_path);
|
||||
bool ret = access(file_path, X_OK) == 0;
|
||||
free(file_path);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,38 +35,38 @@ bool check_if_executable(char *path, char *file_name)
|
||||
*/
|
||||
ssize_t get_dir_list(char ***dir_list, char *path, int ex)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
|
||||
if ((dir = opendir(path)) == NULL)
|
||||
if ((dir = opendir(path)) == NULL)
|
||||
{
|
||||
perror("\nOpendir");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t n = 0;
|
||||
while ((ent = readdir(dir)) != NULL)
|
||||
{
|
||||
if (ex != 0 && !check_if_executable(path, ent->d_name))
|
||||
continue;
|
||||
|
||||
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
n++;
|
||||
*dir_list = realloc(*dir_list, sizeof(char *) * n);
|
||||
(*dir_list)[n - 1] = strdup(ent->d_name);
|
||||
|
||||
if (ent->d_type == DT_DIR)
|
||||
{
|
||||
perror("\nOpendir");
|
||||
return -1;
|
||||
(*dir_list)[n - 1] = realloc((*dir_list)[n - 1], strlen((*dir_list)[n - 1]) + 2);
|
||||
(*dir_list)[n - 1] = strcat((*dir_list)[n - 1], "/");
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t n = 0;
|
||||
while ((ent = readdir(dir)) != NULL)
|
||||
{
|
||||
if (ex != 0 && !check_if_executable(path, ent->d_name))
|
||||
continue;
|
||||
closedir(dir);
|
||||
|
||||
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
n++;
|
||||
*dir_list = realloc(*dir_list, sizeof(char *) * n);
|
||||
(*dir_list)[n - 1] = strdup(ent->d_name);
|
||||
|
||||
if (ent->d_type == DT_DIR)
|
||||
{
|
||||
(*dir_list)[n - 1] = realloc((*dir_list)[n - 1], strlen((*dir_list)[n - 1]) + 2);
|
||||
(*dir_list)[n - 1] = strcat((*dir_list)[n - 1], "/");
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,14 +78,14 @@ ssize_t get_dir_list(char ***dir_list, char *path, int ex)
|
||||
*/
|
||||
ssize_t append_builtin_list(char ***commands_list, ssize_t *size)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
(*size)++;
|
||||
*commands_list = realloc(*commands_list, sizeof(char *) * *size);
|
||||
(*commands_list)[*size - 1] = strdup(builtin[i]);
|
||||
}
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
(*size)++;
|
||||
*commands_list = realloc(*commands_list, sizeof(char *) * *size);
|
||||
(*commands_list)[*size - 1] = strdup(builtin[i]);
|
||||
}
|
||||
|
||||
return *size;
|
||||
return *size;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,70 +98,70 @@ ssize_t append_builtin_list(char ***commands_list, ssize_t *size)
|
||||
*/
|
||||
ssize_t get_complete_options(char ***opts, char *line, char **to_complete)
|
||||
{
|
||||
char **args = NULL, **folders = calloc(0, sizeof(char *));
|
||||
ssize_t sz;
|
||||
char **args = NULL, **folders = calloc(0, sizeof(char *));
|
||||
ssize_t sz;
|
||||
|
||||
int am = sep_string(line, &args, " "), path_depth = 0;
|
||||
int am = sep_string(line, &args, " "), path_depth = 0;
|
||||
|
||||
char *last_arg = args[am - 1];
|
||||
char *last_arg = args[am - 1];
|
||||
|
||||
if (am > 0)
|
||||
if (am > 0)
|
||||
{
|
||||
path_depth = sep_string(last_arg, &folders, "/");
|
||||
*to_complete = strdup(folders[path_depth - 1]);
|
||||
|
||||
char *curr_pos = NULL;
|
||||
|
||||
if (last_arg[0] == '/')
|
||||
{
|
||||
path_depth = sep_string(last_arg, &folders, "/");
|
||||
*to_complete = strdup(folders[path_depth - 1]);
|
||||
|
||||
char *curr_pos = NULL;
|
||||
|
||||
if (last_arg[0] == '/')
|
||||
{
|
||||
curr_pos = strdup("");
|
||||
}
|
||||
else if (strchr(line, ' ') && strcmp(args[am - 2], "||") != 0 && strcmp(args[am - 2], "|") != 0 && strcmp(args[am - 2], "&&") != 0 && strcmp(args[am - 2], ";") != 0 && line[strlen(line) - 2] != ';' && line[strlen(line) - 2] != '&' && line[strlen(line) - 2] != '|')
|
||||
{
|
||||
curr_pos = strdup(".");
|
||||
}
|
||||
else if (last_arg[0] == '.' && last_arg[1] == '/')
|
||||
{
|
||||
curr_pos = strdup(folders[0]);
|
||||
}
|
||||
else
|
||||
goto ABSOLUTE;
|
||||
|
||||
for (int i = 0; i < (path_depth - 1); i++)
|
||||
{
|
||||
curr_pos = realloc(curr_pos, strlen(curr_pos) + strlen(folders[i]) + 2);
|
||||
curr_pos = strcat(curr_pos, "/");
|
||||
curr_pos = strcat(curr_pos, folders[i]);
|
||||
}
|
||||
sz = get_dir_list(opts, curr_pos, 0);
|
||||
|
||||
free(curr_pos);
|
||||
curr_pos = strdup("");
|
||||
}
|
||||
else if (strchr(line, ' ') && strcmp(args[am - 2], "||") != 0 && strcmp(args[am - 2], "|") != 0 && strcmp(args[am - 2], "&&") != 0 && strcmp(args[am - 2], ";") != 0 && line[strlen(line) - 2] != ';' && line[strlen(line) - 2] != '&' && line[strlen(line) - 2] != '|')
|
||||
{
|
||||
curr_pos = strdup(".");
|
||||
}
|
||||
else if (last_arg[0] == '.' && last_arg[1] == '/')
|
||||
{
|
||||
curr_pos = strdup(folders[0]);
|
||||
}
|
||||
else
|
||||
goto ABSOLUTE;
|
||||
|
||||
for (int i = 0; i < (path_depth - 1); i++)
|
||||
{
|
||||
*to_complete = strdup(line);
|
||||
ABSOLUTE:
|
||||
if ((*to_complete)[0] != '\0' && am >= 2)
|
||||
if (strcmp(args[am - 2], "||") == 0 || strcmp(args[am - 2], "&&") == 0 || strcmp(args[am - 2], ";") == 0)
|
||||
*to_complete = strdup("");
|
||||
|
||||
sz = get_path_commands_list(opts);
|
||||
|
||||
append_builtin_list(opts, &sz);
|
||||
curr_pos = realloc(curr_pos, strlen(curr_pos) + strlen(folders[i]) + 2);
|
||||
curr_pos = strcat(curr_pos, "/");
|
||||
curr_pos = strcat(curr_pos, folders[i]);
|
||||
}
|
||||
sz = get_dir_list(opts, curr_pos, 0);
|
||||
|
||||
free_str_arr(args, am);
|
||||
free_str_arr(folders, path_depth);
|
||||
free(curr_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
*to_complete = strdup(line);
|
||||
ABSOLUTE:
|
||||
if ((*to_complete)[0] != '\0' && am >= 2)
|
||||
if (strcmp(args[am - 2], "||") == 0 || strcmp(args[am - 2], "&&") == 0 || strcmp(args[am - 2], ";") == 0)
|
||||
*to_complete = strdup("");
|
||||
|
||||
if (sz < 0)
|
||||
return sz;
|
||||
sz = get_path_commands_list(opts);
|
||||
|
||||
if ((*to_complete)[0] != '\0')
|
||||
{
|
||||
sz = filter_options(opts, &sz, *to_complete);
|
||||
}
|
||||
append_builtin_list(opts, &sz);
|
||||
}
|
||||
|
||||
free_str_arr(args, am);
|
||||
free_str_arr(folders, path_depth);
|
||||
|
||||
if (sz < 0)
|
||||
return sz;
|
||||
|
||||
if ((*to_complete)[0] != '\0')
|
||||
{
|
||||
sz = filter_options(opts, &sz, *to_complete);
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,59 +174,59 @@ ssize_t get_complete_options(char ***opts, char *line, char **to_complete)
|
||||
*/
|
||||
ssize_t filter_options(char ***comp_list, ssize_t *size, char *filter_string)
|
||||
{
|
||||
if (*size < 0)
|
||||
return *size;
|
||||
|
||||
struct tree_node *child_dirs_root = get_new_node();
|
||||
for (ssize_t i = 0; i < *size; i++)
|
||||
insert_tree(child_dirs_root, (*comp_list)[i]);
|
||||
|
||||
char **folders = NULL;
|
||||
int path_depth = sep_string(filter_string, &folders, "/");
|
||||
|
||||
char *last_option = strdup(filter_string);
|
||||
|
||||
if (path_depth > 0)
|
||||
{
|
||||
free(last_option);
|
||||
last_option = folders[path_depth - 1];
|
||||
}
|
||||
|
||||
*size = list_strings_containing(child_dirs_root, last_option, comp_list);
|
||||
|
||||
free_tree(child_dirs_root);
|
||||
free_str_arr(folders, path_depth);
|
||||
|
||||
if (*size < 0)
|
||||
return *size;
|
||||
|
||||
struct tree_node *child_dirs_root = get_new_node();
|
||||
for (ssize_t i = 0; i < *size; i++)
|
||||
insert_tree(child_dirs_root, (*comp_list)[i]);
|
||||
|
||||
char **folders = NULL;
|
||||
int path_depth = sep_string(filter_string, &folders, "/");
|
||||
|
||||
char *last_option = strdup(filter_string);
|
||||
|
||||
if (path_depth > 0)
|
||||
{
|
||||
free(last_option);
|
||||
last_option = folders[path_depth - 1];
|
||||
}
|
||||
|
||||
*size = list_strings_containing(child_dirs_root, last_option, comp_list);
|
||||
|
||||
free_tree(child_dirs_root);
|
||||
free_str_arr(folders, path_depth);
|
||||
|
||||
return *size;
|
||||
}
|
||||
|
||||
ssize_t get_path_commands_list(char ***opts)
|
||||
{
|
||||
char *paths_str = get_env_var("PATH");
|
||||
if (paths_str == NULL)
|
||||
return -1;
|
||||
char *paths_str = get_env_var("PATH");
|
||||
if (paths_str == NULL)
|
||||
return -1;
|
||||
|
||||
char **paths = NULL;
|
||||
int path_am = sep_string(paths_str, &paths, ":");
|
||||
ssize_t sz = 0;
|
||||
char **paths = NULL;
|
||||
int path_am = sep_string(paths_str, &paths, ":");
|
||||
ssize_t sz = 0;
|
||||
|
||||
for (int i = 0; i < path_am; i++)
|
||||
for (int i = 0; i < path_am; i++)
|
||||
{
|
||||
char **tmp_list = malloc(0);
|
||||
ssize_t tmp_sz = get_dir_list(&tmp_list, paths[i], 1);
|
||||
if (tmp_sz < 0)
|
||||
continue;
|
||||
|
||||
for (long j = 0; j < tmp_sz; j++)
|
||||
{
|
||||
char **tmp_list = malloc(0);
|
||||
ssize_t tmp_sz = get_dir_list(&tmp_list, paths[i], 1);
|
||||
if (tmp_sz < 0)
|
||||
continue;
|
||||
if (i != 0)
|
||||
if (str_is_in_arr(*opts, sz, tmp_list[j]))
|
||||
continue;
|
||||
|
||||
for (long j = 0; j < tmp_sz; j++)
|
||||
{
|
||||
if (i != 0)
|
||||
if (str_is_in_arr(*opts, sz, tmp_list[j]))
|
||||
continue;
|
||||
|
||||
append_to_str_arr(opts, &sz, tmp_list[j]);
|
||||
}
|
||||
append_to_str_arr(opts, &sz, tmp_list[j]);
|
||||
}
|
||||
}
|
||||
|
||||
free(paths_str);
|
||||
return sz;
|
||||
free(paths_str);
|
||||
return sz;
|
||||
}
|
310
src/execute.c
310
src/execute.c
@ -4,16 +4,16 @@
|
||||
|
||||
/* Global definitions */
|
||||
char *builtin[] = {
|
||||
"cd",
|
||||
"exec",
|
||||
"export",
|
||||
"exit"};
|
||||
"cd",
|
||||
"exec",
|
||||
"export",
|
||||
"exit"};
|
||||
|
||||
int (*builtin_func[])(char **) = {
|
||||
&sh_cd,
|
||||
&sh_exec,
|
||||
&sh_export,
|
||||
&sh_exit};
|
||||
&sh_cd,
|
||||
&sh_exec,
|
||||
&sh_export,
|
||||
&sh_exit};
|
||||
|
||||
/**
|
||||
* @brief Redirects command input/output and executes it
|
||||
@ -23,28 +23,28 @@ int (*builtin_func[])(char **) = {
|
||||
*/
|
||||
int execute_with_pipes(cmds_p *command)
|
||||
{
|
||||
cmd_pipe *curr = command->pipe;
|
||||
int status = 0, tmp_fd[2] = {-1};
|
||||
cmd_pipe *curr = command->pipe;
|
||||
int status = 0, tmp_fd[2] = {-1};
|
||||
|
||||
for (int i = 0; i < command->pipes_am - 1 && curr != NULL && status == 0; i++)
|
||||
for (int i = 0; i < command->pipes_am - 1 && curr != NULL && status == 0; i++)
|
||||
{
|
||||
if (pipe(tmp_fd) < 0)
|
||||
{
|
||||
if (pipe(tmp_fd) < 0)
|
||||
{
|
||||
perror("pipe");
|
||||
return 1;
|
||||
}
|
||||
|
||||
curr->pipefd[1] = tmp_fd[1];
|
||||
curr->next->pipefd[0] = tmp_fd[0];
|
||||
|
||||
status = execute(curr, command->envs);
|
||||
|
||||
curr = curr->next;
|
||||
perror("pipe");
|
||||
return 1;
|
||||
}
|
||||
|
||||
curr->pipefd[1] = tmp_fd[1];
|
||||
curr->next->pipefd[0] = tmp_fd[0];
|
||||
|
||||
status = execute(curr, command->envs);
|
||||
|
||||
return status;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
status = execute(curr, command->envs);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,22 +55,22 @@ int execute_with_pipes(cmds_p *command)
|
||||
*/
|
||||
int execute(cmd_pipe *command, char **envp)
|
||||
{
|
||||
if (command->args[0] == NULL)
|
||||
return 1;
|
||||
if (command->args[0] == NULL)
|
||||
return 1;
|
||||
|
||||
char **args = command->args;
|
||||
char **args = command->args;
|
||||
|
||||
if (strcmp(args[0], "!") == 0)
|
||||
{
|
||||
args = slice_array(args, 1, -1, true);
|
||||
command->args = args;
|
||||
}
|
||||
if (strcmp(args[0], "!") == 0)
|
||||
{
|
||||
args = slice_array(args, 1, -1, true);
|
||||
command->args = args;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BUILTIN_NUM; i++)
|
||||
if (strcmp(args[0], builtin[i]) == 0)
|
||||
return (*builtin_func[i])(args);
|
||||
for (int i = 0; i < BUILTIN_NUM; i++)
|
||||
if (strcmp(args[0], builtin[i]) == 0)
|
||||
return (*builtin_func[i])(args);
|
||||
|
||||
return launch(command, envp);
|
||||
return launch(command, envp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,37 +81,37 @@ int execute(cmd_pipe *command, char **envp)
|
||||
*/
|
||||
int launch(cmd_pipe *command, char **envp)
|
||||
{
|
||||
pid_t pid, wpid;
|
||||
int status;
|
||||
pid_t pid, wpid;
|
||||
int status;
|
||||
|
||||
pid = fork();
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
redirect_fd(command->pipefd[0], STDIN_FILENO);
|
||||
if (pid == 0)
|
||||
{
|
||||
redirect_fd(command->pipefd[0], STDIN_FILENO);
|
||||
|
||||
redirect_fd(command->pipefd[1], STDOUT_FILENO);
|
||||
redirect_fd(command->pipefd[1], STDOUT_FILENO);
|
||||
|
||||
sh_exec(command->args, envp);
|
||||
}
|
||||
else if (pid < 0)
|
||||
{
|
||||
perror("mshell");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
if (command->pipefd[j] > 2)
|
||||
close(command->pipefd[j]);
|
||||
do
|
||||
wpid = waitpid(pid, &status, WUNTRACED);
|
||||
while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||
}
|
||||
sh_exec(command->args, envp);
|
||||
}
|
||||
else if (pid < 0)
|
||||
{
|
||||
perror("mshell");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
if (command->pipefd[j] > 2)
|
||||
close(command->pipefd[j]);
|
||||
do
|
||||
wpid = waitpid(pid, &status, WUNTRACED);
|
||||
while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||
}
|
||||
|
||||
change_mode(1);
|
||||
change_mode(1);
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,23 +122,23 @@ int launch(cmd_pipe *command, char **envp)
|
||||
*/
|
||||
int sh_cd(char **args)
|
||||
{
|
||||
if (args[1] == NULL)
|
||||
{
|
||||
char *home_env = get_env_var("HOME");
|
||||
if (home_env == NULL)
|
||||
return 1;
|
||||
if (args[1] == NULL)
|
||||
{
|
||||
char *home_env = get_env_var("HOME");
|
||||
if (home_env == NULL)
|
||||
return 1;
|
||||
|
||||
chdir(home_env);
|
||||
free(home_env);
|
||||
}
|
||||
chdir(home_env);
|
||||
free(home_env);
|
||||
}
|
||||
|
||||
else if (chdir(args[1]) < 0)
|
||||
{
|
||||
perror("cd");
|
||||
return 1;
|
||||
}
|
||||
else if (chdir(args[1]) < 0)
|
||||
{
|
||||
perror("cd");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,44 +149,44 @@ int sh_cd(char **args)
|
||||
*/
|
||||
int sh_exec(char **args, char **envp)
|
||||
{
|
||||
change_mode(0);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
change_mode(0);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
if (strcmp(args[0], "exec") == 0)
|
||||
args = slice_array(args, 1, -1, 1);
|
||||
if (strcmp(args[0], "exec") == 0)
|
||||
args = slice_array(args, 1, -1, 1);
|
||||
|
||||
if (mexecvpe(args[0], args, envp) < 0)
|
||||
{
|
||||
perror("mshell");
|
||||
}
|
||||
if (mexecvpe(args[0], args, envp) < 0)
|
||||
{
|
||||
perror("mshell");
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int sh_export(char **args)
|
||||
{
|
||||
if (args[1] == NULL)
|
||||
{
|
||||
for (int i = 0; environ[i] != NULL; i++)
|
||||
printf("declare -x %s\n", environ[i]);
|
||||
if (args[1] == NULL)
|
||||
{
|
||||
for (int i = 0; environ[i] != NULL; i++)
|
||||
printf("declare -x %s\n", environ[i]);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 1; args[i] != NULL; i++)
|
||||
{
|
||||
char *name = strtok(args[i], "="), *val = strtok(NULL, "=");
|
||||
|
||||
if (name == NULL || val == NULL)
|
||||
{
|
||||
fprintf(stderr, "export: wrong arguments\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 1; args[i] != NULL; i++)
|
||||
{
|
||||
char *name = strtok(args[i], "="), *val = strtok(NULL, "=");
|
||||
setenv(name, val, true);
|
||||
|
||||
if (name == NULL || val == NULL)
|
||||
{
|
||||
fprintf(stderr, "export: wrong arguments\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
setenv(name, val, true);
|
||||
|
||||
printf("Set %s variable to %s\n", name, getenv(name));
|
||||
}
|
||||
printf("Set %s variable to %s\n", name, getenv(name));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -197,84 +197,84 @@ int sh_export(char **args)
|
||||
*/
|
||||
int sh_exit(char **args)
|
||||
{
|
||||
exit(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void redirect_fd(int old, int new)
|
||||
{
|
||||
if (old > 0)
|
||||
if (old != new)
|
||||
{
|
||||
if (dup2(old, new) < 0)
|
||||
perror("dup2");
|
||||
else
|
||||
close(old);
|
||||
}
|
||||
if (old > 0)
|
||||
if (old != new)
|
||||
{
|
||||
if (dup2(old, new) < 0)
|
||||
perror("dup2");
|
||||
else
|
||||
close(old);
|
||||
}
|
||||
}
|
||||
|
||||
int mexecvpe(char *file, char **argv, char **envp)
|
||||
{
|
||||
if (file == NULL || file[0] == '\0')
|
||||
return -1;
|
||||
if (file == NULL || file[0] == '\0')
|
||||
return -1;
|
||||
|
||||
if (envp == NULL || envp[0] == NULL)
|
||||
execvp(file, argv);
|
||||
if (envp == NULL || envp[0] == NULL)
|
||||
execvp(file, argv);
|
||||
|
||||
int res = complete_envs(&envp);
|
||||
int res = complete_envs(&envp);
|
||||
|
||||
if (res < 0)
|
||||
return -1;
|
||||
if (res < 0)
|
||||
return -1;
|
||||
|
||||
if (strchr(file, '/') != NULL)
|
||||
execve(file, argv, envp);
|
||||
if (strchr(file, '/') != NULL)
|
||||
execve(file, argv, envp);
|
||||
|
||||
char *path = get_env_var("PATH");
|
||||
if (path == NULL)
|
||||
return -1;
|
||||
char *path = get_env_var("PATH");
|
||||
if (path == NULL)
|
||||
return -1;
|
||||
|
||||
size_t file_len = strlen(file) + 1, path_len = strlen(path) + 1;
|
||||
size_t file_len = strlen(file) + 1, path_len = strlen(path) + 1;
|
||||
|
||||
char buff[file_len + path_len + 1], *subp;
|
||||
char buff[file_len + path_len + 1], *subp;
|
||||
|
||||
for (char *p = path;; p = subp)
|
||||
{
|
||||
subp = strchr(p, ':');
|
||||
memcpy(buff, p, subp - p);
|
||||
for (char *p = path;; p = subp)
|
||||
{
|
||||
subp = strchr(p, ':');
|
||||
memcpy(buff, p, subp - p);
|
||||
|
||||
buff[subp - p] = '/';
|
||||
buff[subp - p] = '/';
|
||||
|
||||
memcpy(buff + (subp - p) + (p < subp), file, file_len);
|
||||
memcpy(buff + (subp - p) + (p < subp), file, file_len);
|
||||
|
||||
execve(buff, argv, envp);
|
||||
execve(buff, argv, envp);
|
||||
|
||||
if (*subp++ == '\0')
|
||||
break;
|
||||
}
|
||||
if (*subp++ == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int complete_envs(char ***envp)
|
||||
{
|
||||
for (int i = 0; environ[i] != NULL; i++)
|
||||
for (int i = 0; environ[i] != NULL; i++)
|
||||
{
|
||||
char *name = strtok(strdup(environ[i]), "=");
|
||||
bool modded = false;
|
||||
for (int j = 0; (*envp)[j] != NULL; j++)
|
||||
{
|
||||
char *name = strtok(strdup(environ[i]), "=");
|
||||
bool modded = false;
|
||||
for (int j = 0; (*envp)[j] != NULL; j++)
|
||||
{
|
||||
if (strncmp((*envp)[j], name, strlen(name)) == 0)
|
||||
{
|
||||
modded = true;
|
||||
(*envp)[j] = strdup(environ[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!modded)
|
||||
{
|
||||
ssize_t size = get_null_term_arr_size(*envp);
|
||||
int rs = append_to_str_arr(envp, &size, environ[i]);
|
||||
if (rs < 0)
|
||||
return rs;
|
||||
}
|
||||
if (strncmp((*envp)[j], name, strlen(name)) == 0)
|
||||
{
|
||||
modded = true;
|
||||
(*envp)[j] = strdup(environ[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!modded)
|
||||
{
|
||||
ssize_t size = get_null_term_arr_size(*envp);
|
||||
int rs = append_to_str_arr(envp, &size, environ[i]);
|
||||
if (rs < 0)
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
308
src/history.c
308
src/history.c
@ -9,34 +9,34 @@
|
||||
*/
|
||||
void append_to_history(char *line)
|
||||
{
|
||||
if (term.hist.length > 0)
|
||||
if (strcmp(line, term.hist.content[term.hist.length - 1]) == 0)
|
||||
return;
|
||||
if (term.hist.length > 0)
|
||||
if (strcmp(line, term.hist.content[term.hist.length - 1]) == 0)
|
||||
return;
|
||||
|
||||
if (strncmp(line, "exit", strlen("exit")) == 0)
|
||||
return;
|
||||
if (strncmp(line, "exit", strlen("exit")) == 0)
|
||||
return;
|
||||
|
||||
if (line[0] == '\0')
|
||||
return;
|
||||
if (line[0] == '\0')
|
||||
return;
|
||||
|
||||
term.hist.length++;
|
||||
term.hist.content = (char **)realloc(term.hist.content, term.hist.length * sizeof(char *));
|
||||
term.hist.content[term.hist.length - 1] = strdup(line);
|
||||
term.hist.length++;
|
||||
term.hist.content = (char **)realloc(term.hist.content, term.hist.length * sizeof(char *));
|
||||
term.hist.content[term.hist.length - 1] = strdup(line);
|
||||
|
||||
fseek(term.hist.file, 0, SEEK_END);
|
||||
fprintf(term.hist.file, "%s\n", line);
|
||||
fflush(term.hist.file);
|
||||
fseek(term.hist.file, 0, SEEK_END);
|
||||
fprintf(term.hist.file, "%s\n", line);
|
||||
fflush(term.hist.file);
|
||||
|
||||
term.hist.pos = -1;
|
||||
term.hist.pos = -1;
|
||||
}
|
||||
|
||||
void clear_sub_history()
|
||||
{
|
||||
free(term.hist.sub.content);
|
||||
free(term.hist.sub.content);
|
||||
|
||||
term.hist.sub.content = malloc(0);
|
||||
term.hist.sub.length = -1;
|
||||
term.hist.sub.pos = -1;
|
||||
term.hist.sub.content = malloc(0);
|
||||
term.hist.sub.length = -1;
|
||||
term.hist.sub.pos = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,101 +47,101 @@ void clear_sub_history()
|
||||
*/
|
||||
char *previous_hist_entry(char *line)
|
||||
{
|
||||
static int h_size;
|
||||
int f_len = get_num_of_lines(term.hist.file);
|
||||
static int h_size;
|
||||
int f_len = get_num_of_lines(term.hist.file);
|
||||
|
||||
if (term.hist.length != f_len)
|
||||
if (term.hist.length != f_len)
|
||||
{
|
||||
clear_sub_history();
|
||||
term.hist.pos = -1;
|
||||
|
||||
char **tmp_h = calloc(sizeof(char *), 0);
|
||||
int tmp_h_pos = 0;
|
||||
|
||||
fseek(term.hist.file, 0, SEEK_END);
|
||||
|
||||
while (term.hist.length + tmp_h_pos < f_len && ftell(term.hist.file) > 1)
|
||||
{
|
||||
clear_sub_history();
|
||||
term.hist.pos = -1;
|
||||
char ch = '\0';
|
||||
size_t llen = 0;
|
||||
while (ch != '\n')
|
||||
{
|
||||
fseek(term.hist.file, -2, SEEK_CUR);
|
||||
if (ftell(term.hist.file) < 1)
|
||||
break;
|
||||
ch = fgetc(term.hist.file);
|
||||
}
|
||||
|
||||
char **tmp_h = calloc(sizeof(char *), 0);
|
||||
int tmp_h_pos = 0;
|
||||
long f_pos = ftell(term.hist.file);
|
||||
|
||||
fseek(term.hist.file, 0, SEEK_END);
|
||||
tmp_h = realloc(tmp_h, sizeof(char *) * (tmp_h_pos + 1));
|
||||
getline(&tmp_h[tmp_h_pos], &llen, term.hist.file);
|
||||
|
||||
while (term.hist.length + tmp_h_pos < f_len && ftell(term.hist.file) > 1)
|
||||
{
|
||||
char ch = '\0';
|
||||
size_t llen = 0;
|
||||
while (ch != '\n')
|
||||
{
|
||||
fseek(term.hist.file, -2, SEEK_CUR);
|
||||
if (ftell(term.hist.file) < 1)
|
||||
break;
|
||||
ch = fgetc(term.hist.file);
|
||||
}
|
||||
fseek(term.hist.file, f_pos, SEEK_SET);
|
||||
|
||||
long f_pos = ftell(term.hist.file);
|
||||
if (tmp_h[tmp_h_pos][strlen(tmp_h[tmp_h_pos]) - 1] == '\n')
|
||||
tmp_h[tmp_h_pos][strlen(tmp_h[tmp_h_pos]) - 1] = '\0';
|
||||
|
||||
tmp_h = realloc(tmp_h, sizeof(char *) * (tmp_h_pos + 1));
|
||||
getline(&tmp_h[tmp_h_pos], &llen, term.hist.file);
|
||||
tmp_h_pos++;
|
||||
|
||||
fseek(term.hist.file, f_pos, SEEK_SET);
|
||||
|
||||
if (tmp_h[tmp_h_pos][strlen(tmp_h[tmp_h_pos]) - 1] == '\n')
|
||||
tmp_h[tmp_h_pos][strlen(tmp_h[tmp_h_pos]) - 1] = '\0';
|
||||
|
||||
tmp_h_pos++;
|
||||
|
||||
fseek(term.hist.file, -2, SEEK_CUR);
|
||||
}
|
||||
|
||||
for (int i = 0; i < tmp_h_pos; i++)
|
||||
append_to_str_arr(&term.hist.content, &term.hist.length, tmp_h[i]);
|
||||
|
||||
free_str_arr(tmp_h, tmp_h_pos);
|
||||
fseek(term.hist.file, -2, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (line == NULL)
|
||||
{
|
||||
if (term.hist.pos + 1 == term.hist.length)
|
||||
return NULL;
|
||||
for (int i = 0; i < tmp_h_pos; i++)
|
||||
append_to_str_arr(&term.hist.content, &term.hist.length, tmp_h[i]);
|
||||
|
||||
term.hist.pos++;
|
||||
return strdup(term.hist.content[term.hist.length - term.hist.pos - 1]);
|
||||
}
|
||||
free_str_arr(tmp_h, tmp_h_pos);
|
||||
}
|
||||
|
||||
if (term.hist.sub.length < 0)
|
||||
{
|
||||
if (line == NULL)
|
||||
{
|
||||
if (term.hist.pos + 1 == term.hist.length)
|
||||
return NULL;
|
||||
|
||||
term.hist.pos++;
|
||||
return strdup(term.hist.content[term.hist.length - term.hist.pos - 1]);
|
||||
}
|
||||
|
||||
if (term.hist.sub.length < 0)
|
||||
{
|
||||
term.hist.sub.length++;
|
||||
for (int i = 0; i < term.hist.length; i++)
|
||||
if (strncmp(term.hist.content[i], line, strlen(line)) == 0)
|
||||
{
|
||||
term.hist.sub.length++;
|
||||
for (int i = 0; i < term.hist.length; i++)
|
||||
if (strncmp(term.hist.content[i], line, strlen(line)) == 0)
|
||||
{
|
||||
term.hist.sub.length++;
|
||||
term.hist.sub.content = realloc(term.hist.sub.content, term.hist.sub.length * sizeof(char *));
|
||||
term.hist.sub.content[term.hist.sub.length - 1] = term.hist.content[i];
|
||||
}
|
||||
h_size = term.hist.sub.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
int tmp_len = term.hist.sub.length;
|
||||
term.hist.sub.length = 0;
|
||||
for (int i = 0; i < tmp_len; i++)
|
||||
if (strncmp(term.hist.sub.content[i], line, strlen(line)) == 0)
|
||||
{
|
||||
term.hist.sub.length++;
|
||||
term.hist.sub.content[term.hist.sub.length - 1] = term.hist.sub.content[i];
|
||||
}
|
||||
term.hist.sub.content = realloc(term.hist.sub.content, term.hist.sub.length * sizeof(char *));
|
||||
term.hist.sub.content[term.hist.sub.length - 1] = term.hist.content[i];
|
||||
}
|
||||
h_size = term.hist.sub.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
int tmp_len = term.hist.sub.length;
|
||||
term.hist.sub.length = 0;
|
||||
for (int i = 0; i < tmp_len; i++)
|
||||
if (strncmp(term.hist.sub.content[i], line, strlen(line)) == 0)
|
||||
{
|
||||
term.hist.sub.length++;
|
||||
term.hist.sub.content[term.hist.sub.length - 1] = term.hist.sub.content[i];
|
||||
}
|
||||
term.hist.sub.content = realloc(term.hist.sub.content, term.hist.sub.length * sizeof(char *));
|
||||
|
||||
if (term.hist.sub.length != h_size)
|
||||
{
|
||||
h_size = term.hist.sub.length;
|
||||
term.hist.sub.pos = -1;
|
||||
}
|
||||
}
|
||||
|
||||
term.hist.sub.pos++;
|
||||
|
||||
if (term.hist.sub.pos >= term.hist.sub.length)
|
||||
if (term.hist.sub.length != h_size)
|
||||
{
|
||||
term.hist.sub.pos = term.hist.sub.length - 1;
|
||||
return NULL;
|
||||
h_size = term.hist.sub.length;
|
||||
term.hist.sub.pos = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return strdup(term.hist.sub.content[term.hist.sub.length - term.hist.sub.pos - 1]);
|
||||
term.hist.sub.pos++;
|
||||
|
||||
if (term.hist.sub.pos >= term.hist.sub.length)
|
||||
{
|
||||
term.hist.sub.pos = term.hist.sub.length - 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return strdup(term.hist.sub.content[term.hist.sub.length - term.hist.sub.pos - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,90 +152,90 @@ char *previous_hist_entry(char *line)
|
||||
*/
|
||||
char *next_hist_entry(char *line)
|
||||
{
|
||||
if (line == NULL)
|
||||
{
|
||||
if (term.hist.pos == 0)
|
||||
return NULL;
|
||||
if (line == NULL)
|
||||
{
|
||||
if (term.hist.pos == 0)
|
||||
return NULL;
|
||||
|
||||
term.hist.pos--;
|
||||
return strdup(term.hist.content[term.hist.length - term.hist.pos - 1]);
|
||||
}
|
||||
term.hist.pos--;
|
||||
return strdup(term.hist.content[term.hist.length - term.hist.pos - 1]);
|
||||
}
|
||||
|
||||
if (term.hist.sub.pos <= 0)
|
||||
return NULL;
|
||||
if (term.hist.sub.pos <= 0)
|
||||
return NULL;
|
||||
|
||||
term.hist.sub.pos--;
|
||||
return strdup(term.hist.sub.content[term.hist.sub.length - term.hist.sub.pos - 1]);
|
||||
term.hist.sub.pos--;
|
||||
return strdup(term.hist.sub.content[term.hist.sub.length - term.hist.sub.pos - 1]);
|
||||
}
|
||||
|
||||
void init_history()
|
||||
{
|
||||
term.hist.length = 0;
|
||||
term.hist.pos = -1;
|
||||
term.hist.content = calloc(term.hist.length, sizeof(char *));
|
||||
term.hist.length = 0;
|
||||
term.hist.pos = -1;
|
||||
term.hist.content = calloc(term.hist.length, sizeof(char *));
|
||||
|
||||
term.hist.sub.length = -1;
|
||||
term.hist.sub.pos = -1;
|
||||
term.hist.sub.content = calloc(0, sizeof(char *));
|
||||
term.hist.sub.length = -1;
|
||||
term.hist.sub.pos = -1;
|
||||
term.hist.sub.content = calloc(0, sizeof(char *));
|
||||
|
||||
open_history_file();
|
||||
open_history_file();
|
||||
|
||||
size_t sz = 0;
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
size_t sz = 0;
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
while ((len = getline(&buf, &sz, term.hist.file)) != -1)
|
||||
{
|
||||
char *tmp = strdup(buf);
|
||||
if (tmp[strlen(tmp) - 1] == '\n')
|
||||
tmp[strlen(tmp) - 1] = '\0';
|
||||
while ((len = getline(&buf, &sz, term.hist.file)) != -1)
|
||||
{
|
||||
char *tmp = strdup(buf);
|
||||
if (tmp[strlen(tmp) - 1] == '\n')
|
||||
tmp[strlen(tmp) - 1] = '\0';
|
||||
|
||||
append_to_str_arr(&term.hist.content, &term.hist.length, tmp);
|
||||
free(tmp);
|
||||
}
|
||||
free(buf);
|
||||
append_to_str_arr(&term.hist.content, &term.hist.length, tmp);
|
||||
free(tmp);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void open_history_file()
|
||||
{
|
||||
char *data_path;
|
||||
if ((data_path = get_env_var("XDG_DATA_HOME")) == NULL)
|
||||
{
|
||||
char *user_home;
|
||||
if ((user_home = get_env_var("HOME")) == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
char *data_path;
|
||||
if ((data_path = get_env_var("XDG_DATA_HOME")) == NULL)
|
||||
{
|
||||
char *user_home;
|
||||
if ((user_home = get_env_var("HOME")) == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
data_path = user_home;
|
||||
data_path = realloc(data_path, strlen(data_path) + strlen("/.local/share/") + 1);
|
||||
data_path = strcat(data_path, "/.local/share/");
|
||||
}
|
||||
data_path = user_home;
|
||||
data_path = realloc(data_path, strlen(data_path) + strlen("/.local/share/") + 1);
|
||||
data_path = strcat(data_path, "/.local/share/");
|
||||
}
|
||||
|
||||
struct stat st = {0};
|
||||
if (stat(data_path, &st) < 0)
|
||||
{
|
||||
printf("No %s dir, tying to create\n", data_path);
|
||||
char *buff = malloc(strlen("mkdir -p ") + strlen(data_path) + 1);
|
||||
buff = strdup("mkdir -p ");
|
||||
buff = strcat(buff, data_path);
|
||||
struct stat st = {0};
|
||||
if (stat(data_path, &st) < 0)
|
||||
{
|
||||
printf("No %s dir, tying to create\n", data_path);
|
||||
char *buff = malloc(strlen("mkdir -p ") + strlen(data_path) + 1);
|
||||
buff = strdup("mkdir -p ");
|
||||
buff = strcat(buff, data_path);
|
||||
|
||||
system(buff);
|
||||
}
|
||||
system(buff);
|
||||
}
|
||||
|
||||
data_path = realloc(data_path, strlen(data_path) + strlen(".mshistory") + 1);
|
||||
data_path = strcat(data_path, ".mshistory");
|
||||
data_path = realloc(data_path, strlen(data_path) + strlen(".mshistory") + 1);
|
||||
data_path = strcat(data_path, ".mshistory");
|
||||
|
||||
if ((term.hist.file = fopen(data_path, "a+")) == NULL)
|
||||
{
|
||||
perror("open");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((term.hist.file = fopen(data_path, "a+")) == NULL)
|
||||
{
|
||||
perror("open");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fseek(term.hist.file, 0, SEEK_SET);
|
||||
fseek(term.hist.file, 0, SEEK_SET);
|
||||
|
||||
free(data_path);
|
||||
free(data_path);
|
||||
}
|
||||
|
||||
void close_history_file()
|
||||
{
|
||||
fclose(term.hist.file);
|
||||
fclose(term.hist.file);
|
||||
}
|
288
src/input.c
288
src/input.c
@ -10,17 +10,17 @@
|
||||
*/
|
||||
void change_mode(int on)
|
||||
{
|
||||
static struct termios oldt, newt;
|
||||
static struct termios oldt, newt;
|
||||
|
||||
if (on)
|
||||
{
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
}
|
||||
else
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
if (on)
|
||||
{
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
}
|
||||
else
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -31,82 +31,82 @@ void change_mode(int on)
|
||||
*/
|
||||
char *read_line()
|
||||
{
|
||||
int c;
|
||||
int n = 0, pos = 0;
|
||||
int c;
|
||||
int n = 0, pos = 0;
|
||||
|
||||
char *line = strdup("");
|
||||
char *line = strdup("");
|
||||
|
||||
while (read(STDIN_FILENO, &c, 1))
|
||||
while (read(STDIN_FILENO, &c, 1))
|
||||
{
|
||||
c = process_keypress(c);
|
||||
|
||||
if (c)
|
||||
{
|
||||
c = process_keypress(c);
|
||||
switch (c)
|
||||
{
|
||||
case UP_KEY:
|
||||
up_key(&pos, &n, &line);
|
||||
break;
|
||||
|
||||
if (c)
|
||||
case DOWN_KEY:
|
||||
down_key(&pos, &n, &line);
|
||||
break;
|
||||
|
||||
default:
|
||||
term.hist.pos = -1;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case UP_KEY:
|
||||
up_key(&pos, &n, &line);
|
||||
break;
|
||||
|
||||
case DOWN_KEY:
|
||||
down_key(&pos, &n, &line);
|
||||
break;
|
||||
case DELETE_KEY:
|
||||
delete_key(pos, &n, &line);
|
||||
break;
|
||||
|
||||
default:
|
||||
term.hist.pos = -1;
|
||||
case LEFT_KEY:
|
||||
move_left(&pos);
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case RIGHT_KEY:
|
||||
move_right(&pos, n);
|
||||
break;
|
||||
|
||||
case DELETE_KEY:
|
||||
delete_key(pos, &n, &line);
|
||||
break;
|
||||
case HOME_KEY:
|
||||
home_key(&pos);
|
||||
break;
|
||||
|
||||
case LEFT_KEY:
|
||||
move_left(&pos);
|
||||
break;
|
||||
case END_KEY:
|
||||
end_key(&pos, n);
|
||||
break;
|
||||
|
||||
case RIGHT_KEY:
|
||||
move_right(&pos, n);
|
||||
break;
|
||||
case BACKSPACE_KEY:
|
||||
backspace_key(&pos, &n, &line);
|
||||
break;
|
||||
|
||||
case HOME_KEY:
|
||||
home_key(&pos);
|
||||
break;
|
||||
case ENTER_KEY:
|
||||
new_line(line);
|
||||
|
||||
case END_KEY:
|
||||
end_key(&pos, n);
|
||||
break;
|
||||
return line;
|
||||
break;
|
||||
|
||||
case BACKSPACE_KEY:
|
||||
backspace_key(&pos, &n, &line);
|
||||
break;
|
||||
|
||||
case ENTER_KEY:
|
||||
new_line(line);
|
||||
|
||||
return line;
|
||||
break;
|
||||
|
||||
case TAB_KEY:
|
||||
{
|
||||
tab_key(&pos, &n, &line);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESCAPE_KEY:
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((c > 31 && c < 127) || (c > 127 && c < 255))
|
||||
printable_key(&pos, &n, (char)c, &line);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
case TAB_KEY:
|
||||
{
|
||||
tab_key(&pos, &n, &line);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESCAPE_KEY:
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((c > 31 && c < 127) || (c > 127 && c < 255))
|
||||
printable_key(&pos, &n, (char)c, &line);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,72 +117,72 @@ char *read_line()
|
||||
*/
|
||||
int process_keypress(char c)
|
||||
{
|
||||
char seq[3];
|
||||
if (c == '\x1b')
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (read(STDIN_FILENO, &seq[i], 1) < 0)
|
||||
return ESCAPE_KEY;
|
||||
if (seq[0] == '[')
|
||||
{
|
||||
if (seq[1] >= '0' && seq[1] <= '9')
|
||||
{
|
||||
read(STDIN_FILENO, &seq[2], 1);
|
||||
if (seq[2] == '~')
|
||||
{
|
||||
switch (seq[1])
|
||||
{
|
||||
case '3':
|
||||
return DELETE_KEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (seq[1])
|
||||
{
|
||||
case 'A':
|
||||
return UP_KEY;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
return DOWN_KEY;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
return RIGHT_KEY;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
return LEFT_KEY;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
return END_KEY;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
return HOME_KEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
char seq[3];
|
||||
if (c == '\x1b')
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (read(STDIN_FILENO, &seq[i], 1) < 0)
|
||||
return ESCAPE_KEY;
|
||||
}
|
||||
else if (c == 127)
|
||||
if (seq[0] == '[')
|
||||
{
|
||||
return BACKSPACE_KEY;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
return ENTER_KEY;
|
||||
}
|
||||
else if (c == '\t')
|
||||
{
|
||||
return TAB_KEY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return c;
|
||||
if (seq[1] >= '0' && seq[1] <= '9')
|
||||
{
|
||||
read(STDIN_FILENO, &seq[2], 1);
|
||||
if (seq[2] == '~')
|
||||
{
|
||||
switch (seq[1])
|
||||
{
|
||||
case '3':
|
||||
return DELETE_KEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (seq[1])
|
||||
{
|
||||
case 'A':
|
||||
return UP_KEY;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
return DOWN_KEY;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
return RIGHT_KEY;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
return LEFT_KEY;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
return END_KEY;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
return HOME_KEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ESCAPE_KEY;
|
||||
}
|
||||
else if (c == 127)
|
||||
{
|
||||
return BACKSPACE_KEY;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
return ENTER_KEY;
|
||||
}
|
||||
else if (c == '\t')
|
||||
{
|
||||
return TAB_KEY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,20 +194,20 @@ int process_keypress(char c)
|
||||
*/
|
||||
void free_input(int *pos, int *n, char **line)
|
||||
{
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
|
||||
free(*line);
|
||||
*line = strdup("");
|
||||
*n = 0;
|
||||
free(*line);
|
||||
*line = strdup("");
|
||||
*n = 0;
|
||||
|
||||
for (int i = 0; i < *pos; i++)
|
||||
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
||||
for (int i = 0; i < *pos; i++)
|
||||
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\033[K", 3);
|
||||
append_to_buff(&buff, &buff_size, "\033[K", 3);
|
||||
|
||||
*pos = *n;
|
||||
*pos = *n;
|
||||
|
||||
print_str(buff, buff_size);
|
||||
free(buff);
|
||||
print_str(buff, buff_size);
|
||||
free(buff);
|
||||
}
|
362
src/keys.c
362
src/keys.c
@ -15,22 +15,22 @@
|
||||
*/
|
||||
void delete_key(int pos, int *n, char **line)
|
||||
{
|
||||
if (pos < *n)
|
||||
{
|
||||
remove_on_pos(line, pos + 1);
|
||||
(*n)--;
|
||||
if (pos < *n)
|
||||
{
|
||||
remove_on_pos(line, pos + 1);
|
||||
(*n)--;
|
||||
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + pos, *n - pos);
|
||||
append_to_buff(&buff, &buff_size, " ", 1);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + pos, *n - pos);
|
||||
append_to_buff(&buff, &buff_size, " ", 1);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
free(buff);
|
||||
}
|
||||
print_str(buff, buff_size);
|
||||
free(buff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,35 +43,35 @@ void delete_key(int pos, int *n, char **line)
|
||||
void up_key(int *pos, int *n, char **line)
|
||||
{
|
||||
|
||||
char *buff = strdup("\033[K");
|
||||
size_t buff_size = 4;
|
||||
char *buff = strdup("\033[K");
|
||||
size_t buff_size = 4;
|
||||
|
||||
char *entry = NULL;
|
||||
char *entry = NULL;
|
||||
|
||||
if (*pos == 0)
|
||||
entry = previous_hist_entry(NULL);
|
||||
else
|
||||
{
|
||||
(*line)[*pos] = '\0';
|
||||
entry = previous_hist_entry(*line);
|
||||
}
|
||||
if (*pos == 0)
|
||||
entry = previous_hist_entry(NULL);
|
||||
else
|
||||
{
|
||||
(*line)[*pos] = '\0';
|
||||
entry = previous_hist_entry(*line);
|
||||
}
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
free(buff);
|
||||
return;
|
||||
}
|
||||
|
||||
free(*line);
|
||||
*line = entry;
|
||||
*n = strlen(*line);
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
if (entry == NULL)
|
||||
{
|
||||
free(buff);
|
||||
return;
|
||||
}
|
||||
|
||||
free(*line);
|
||||
*line = entry;
|
||||
*n = strlen(*line);
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
free(buff);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,57 +84,57 @@ void up_key(int *pos, int *n, char **line)
|
||||
void down_key(int *pos, int *n, char **line)
|
||||
{
|
||||
|
||||
char *buff = strdup("\033[K");
|
||||
size_t buff_size = 4;
|
||||
char *buff = strdup("\033[K");
|
||||
size_t buff_size = 4;
|
||||
|
||||
char *entry = NULL;
|
||||
char *entry = NULL;
|
||||
|
||||
if (*pos == 0)
|
||||
if (*pos == 0)
|
||||
{
|
||||
if (term.hist.pos <= 0)
|
||||
{
|
||||
if (term.hist.pos <= 0)
|
||||
{
|
||||
if (term.hist.pos == 0)
|
||||
term.hist.pos--;
|
||||
if (term.hist.pos == 0)
|
||||
term.hist.pos--;
|
||||
|
||||
free(buff);
|
||||
free_input(pos, n, line);
|
||||
return;
|
||||
}
|
||||
|
||||
entry = next_hist_entry(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*line)[*pos] = '\0';
|
||||
|
||||
if (term.hist.sub.pos <= 0)
|
||||
{
|
||||
if (term.hist.sub.pos == 0)
|
||||
term.hist.sub.pos--;
|
||||
|
||||
free(buff);
|
||||
free_input(pos, n, line);
|
||||
return;
|
||||
}
|
||||
|
||||
entry = next_hist_entry(*line);
|
||||
free(buff);
|
||||
free_input(pos, n, line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry == NULL)
|
||||
entry = next_hist_entry(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*line)[*pos] = '\0';
|
||||
|
||||
if (term.hist.sub.pos <= 0)
|
||||
{
|
||||
free(buff);
|
||||
return;
|
||||
if (term.hist.sub.pos == 0)
|
||||
term.hist.sub.pos--;
|
||||
|
||||
free(buff);
|
||||
free_input(pos, n, line);
|
||||
return;
|
||||
}
|
||||
|
||||
*line = entry;
|
||||
*n = strlen(*line);
|
||||
entry = next_hist_entry(*line);
|
||||
}
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
if (entry == NULL)
|
||||
{
|
||||
free(buff);
|
||||
return;
|
||||
}
|
||||
|
||||
*line = entry;
|
||||
*n = strlen(*line);
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
free(buff);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,12 +144,12 @@ void down_key(int *pos, int *n, char **line)
|
||||
*/
|
||||
void move_left(int *pos)
|
||||
{
|
||||
clear_sub_history();
|
||||
if (*pos > 0)
|
||||
{
|
||||
print_str("\033[D", 3);
|
||||
(*pos)--;
|
||||
}
|
||||
clear_sub_history();
|
||||
if (*pos > 0)
|
||||
{
|
||||
print_str("\033[D", 3);
|
||||
(*pos)--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,13 +160,13 @@ void move_left(int *pos)
|
||||
*/
|
||||
void move_right(int *pos, int n)
|
||||
{
|
||||
if (*pos < n)
|
||||
{
|
||||
print_str("\033[C", 3);
|
||||
(*pos)++;
|
||||
if (*pos < n)
|
||||
{
|
||||
print_str("\033[C", 3);
|
||||
(*pos)++;
|
||||
|
||||
clear_sub_history();
|
||||
}
|
||||
clear_sub_history();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,18 +176,18 @@ void move_right(int *pos, int n)
|
||||
*/
|
||||
void home_key(int *pos)
|
||||
{
|
||||
clear_sub_history();
|
||||
clear_sub_history();
|
||||
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
|
||||
for (int i = 0; i < *pos; i++)
|
||||
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
||||
for (int i = 0; i < *pos; i++)
|
||||
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
*pos = 0;
|
||||
print_str(buff, buff_size);
|
||||
*pos = 0;
|
||||
|
||||
free(buff);
|
||||
free(buff);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,17 +198,17 @@ void home_key(int *pos)
|
||||
*/
|
||||
void end_key(int *pos, int n)
|
||||
{
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
|
||||
for (int i = 0; i < n - *pos; i++)
|
||||
append_to_buff(&buff, &buff_size, "\033[C", 3);
|
||||
for (int i = 0; i < n - *pos; i++)
|
||||
append_to_buff(&buff, &buff_size, "\033[C", 3);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
print_str(buff, buff_size);
|
||||
|
||||
*pos = n;
|
||||
*pos = n;
|
||||
|
||||
free(buff);
|
||||
free(buff);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,27 +220,27 @@ void end_key(int *pos, int n)
|
||||
*/
|
||||
void backspace_key(int *pos, int *n, char **line)
|
||||
{
|
||||
if (*pos > 0)
|
||||
{
|
||||
clear_sub_history();
|
||||
if (*pos > 0)
|
||||
{
|
||||
clear_sub_history();
|
||||
|
||||
remove_on_pos(line, *pos);
|
||||
(*n)--;
|
||||
(*pos)--;
|
||||
remove_on_pos(line, *pos);
|
||||
(*n)--;
|
||||
(*pos)--;
|
||||
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, " ", 1);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, " ", 1);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
print_str(buff, buff_size);
|
||||
|
||||
free(buff);
|
||||
}
|
||||
free(buff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,9 +249,9 @@ void backspace_key(int *pos, int *n, char **line)
|
||||
*/
|
||||
void new_line(char *line)
|
||||
{
|
||||
append_to_history(line);
|
||||
clear_sub_history();
|
||||
print_str("\n", 1);
|
||||
append_to_history(line);
|
||||
clear_sub_history();
|
||||
print_str("\n", 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,63 +263,63 @@ void new_line(char *line)
|
||||
*/
|
||||
void tab_key(int *pos, int *n, char **line)
|
||||
{
|
||||
clear_sub_history();
|
||||
clear_sub_history();
|
||||
|
||||
(*line)[*pos] = '\0';
|
||||
*line = realloc(*line, strlen(*line) + 1);
|
||||
(*line)[*pos] = '\0';
|
||||
*line = realloc(*line, strlen(*line) + 1);
|
||||
|
||||
char *tmp = trim_string(*line, true);
|
||||
free(*line);
|
||||
*line = tmp;
|
||||
char *tmp = trim_string(*line, true);
|
||||
free(*line);
|
||||
*line = tmp;
|
||||
|
||||
*pos = strlen(*line);
|
||||
*pos = strlen(*line);
|
||||
*n = *pos;
|
||||
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
|
||||
char **complete_options = calloc(0, sizeof(char *)), *to_complete = NULL;
|
||||
size_t opts_sz = get_complete_options(&complete_options, *line, &to_complete);
|
||||
|
||||
if (opts_sz == 1)
|
||||
{
|
||||
char *ending = complete_options[0] + strlen(to_complete);
|
||||
*pos += strlen(ending);
|
||||
*n = *pos;
|
||||
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
*line = realloc(*line, strlen(*line) + strlen(ending) + 1);
|
||||
*line = strcat(*line, ending);
|
||||
|
||||
char **complete_options = calloc(0, sizeof(char *)), *to_complete = NULL;
|
||||
size_t opts_sz = get_complete_options(&complete_options, *line, &to_complete);
|
||||
append_to_buff(&buff, &buff_size, ending, strlen(ending));
|
||||
}
|
||||
else
|
||||
{
|
||||
append_to_buff(&buff, &buff_size, "\n", 1);
|
||||
|
||||
if (opts_sz == 1)
|
||||
if ((int)opts_sz < 1)
|
||||
{
|
||||
char *ending = complete_options[0] + strlen(to_complete);
|
||||
*pos += strlen(ending);
|
||||
*n = *pos;
|
||||
|
||||
*line = realloc(*line, strlen(*line) + strlen(ending) + 1);
|
||||
*line = strcat(*line, ending);
|
||||
|
||||
append_to_buff(&buff, &buff_size, ending, strlen(ending));
|
||||
}
|
||||
else
|
||||
{
|
||||
append_to_buff(&buff, &buff_size, "\n", 1);
|
||||
|
||||
if ((int)opts_sz < 1)
|
||||
{
|
||||
append_to_buff(&buff, &buff_size, "No suggestions", strlen("No suggestions"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)opts_sz; i++)
|
||||
{
|
||||
append_to_buff(&buff, &buff_size, complete_options[i], strlen(complete_options[i]));
|
||||
append_to_buff(&buff, &buff_size, " ", 1);
|
||||
}
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\n", 1);
|
||||
|
||||
char *prompt = compose_prompt();
|
||||
append_to_buff(&buff, &buff_size, prompt, strlen(prompt));
|
||||
free(prompt);
|
||||
|
||||
append_to_buff(&buff, &buff_size, *line, *pos);
|
||||
append_to_buff(&buff, &buff_size, "No suggestions", strlen("No suggestions"));
|
||||
}
|
||||
|
||||
print_str(buff, buff_size);
|
||||
for (int i = 0; i < (int)opts_sz; i++)
|
||||
{
|
||||
append_to_buff(&buff, &buff_size, complete_options[i], strlen(complete_options[i]));
|
||||
append_to_buff(&buff, &buff_size, " ", 1);
|
||||
}
|
||||
|
||||
free(buff);
|
||||
free(to_complete);
|
||||
append_to_buff(&buff, &buff_size, "\n", 1);
|
||||
|
||||
char *prompt = compose_prompt();
|
||||
append_to_buff(&buff, &buff_size, prompt, strlen(prompt));
|
||||
free(prompt);
|
||||
|
||||
append_to_buff(&buff, &buff_size, *line, *pos);
|
||||
}
|
||||
|
||||
print_str(buff, buff_size);
|
||||
|
||||
free(buff);
|
||||
free(to_complete);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -332,20 +332,20 @@ void tab_key(int *pos, int *n, char **line)
|
||||
*/
|
||||
void printable_key(int *pos, int *n, char c, char **line)
|
||||
{
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
char *buff = strdup("");
|
||||
size_t buff_size = 1;
|
||||
|
||||
(*n)++;
|
||||
append_to_buff(&buff, &buff_size, &c, 1);
|
||||
(*n)++;
|
||||
append_to_buff(&buff, &buff_size, &c, 1);
|
||||
|
||||
append_to_pos(line, *pos, c);
|
||||
append_to_pos(line, *pos, c);
|
||||
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
(*pos)++;
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||
(*pos)++;
|
||||
append_to_buff(&buff, &buff_size, *line + *pos, *n - *pos);
|
||||
append_to_buff(&buff, &buff_size, "\0338", 2);
|
||||
|
||||
print_str(buff, buff_size);
|
||||
print_str(buff, buff_size);
|
||||
|
||||
free(buff);
|
||||
free(buff);
|
||||
}
|
574
src/line_parce.c
574
src/line_parce.c
@ -10,307 +10,307 @@
|
||||
*/
|
||||
cmds_p *process_line(char *line)
|
||||
{
|
||||
int line_size = strlen(line);
|
||||
int line_size = strlen(line);
|
||||
|
||||
if (line_size < 1)
|
||||
return NULL;
|
||||
if (line_size < 1)
|
||||
return NULL;
|
||||
|
||||
char *tmp = strdup(line), *free_tmp = tmp;
|
||||
cmds_p *coms = new_cmd();
|
||||
char *tmp = strdup(line), *free_tmp = tmp;
|
||||
cmds_p *coms = new_cmd();
|
||||
|
||||
cmds_p *curr_cmd = coms;
|
||||
cmd_pipe *curr_pipe = curr_cmd->pipe;
|
||||
curr_pipe->pipefd[0] = STDIN_FILENO;
|
||||
cmds_p *curr_cmd = coms;
|
||||
cmd_pipe *curr_pipe = curr_cmd->pipe;
|
||||
curr_pipe->pipefd[0] = STDIN_FILENO;
|
||||
|
||||
for (int i = 0; i < line_size; i++)
|
||||
for (int i = 0; i < line_size; i++)
|
||||
{
|
||||
if (line[i] == '"')
|
||||
{
|
||||
if (line[i] == '"')
|
||||
tmp++;
|
||||
i++;
|
||||
int j = i;
|
||||
for (; j < line_size; j++)
|
||||
if (line[j] == '"')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
int j = i;
|
||||
for (; j < line_size; j++)
|
||||
if (line[j] == '"')
|
||||
{
|
||||
free_tmp[j] = '\0';
|
||||
free_tmp[j] = '\0';
|
||||
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
|
||||
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
|
||||
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= line_size)
|
||||
{
|
||||
char *ap_line = read_line();
|
||||
|
||||
line = realloc(line, strlen(line) + strlen(ap_line) + 1);
|
||||
line = strcat(line, ap_line);
|
||||
|
||||
line_size = strlen(line);
|
||||
|
||||
free(ap_line);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
i = j;
|
||||
|
||||
if (tmp[0] == ' ')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (line[i] == ';' || (line[i] == '&' && line[i + 1] == '&') || (line[i] == '|' && line[i + 1] == '|'))
|
||||
{
|
||||
free_tmp[i] = '\0';
|
||||
if (line[i - 1] != ' ')
|
||||
{
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
|
||||
}
|
||||
else
|
||||
tmp++;
|
||||
|
||||
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
|
||||
curr_pipe->args[curr_pipe->args_am] = NULL;
|
||||
if (j >= line_size)
|
||||
{
|
||||
char *ap_line = read_line();
|
||||
|
||||
switch (line[i])
|
||||
{
|
||||
case ';':
|
||||
curr_cmd->sep_next = SEMICOLON_SEP;
|
||||
break;
|
||||
line = realloc(line, strlen(line) + strlen(ap_line) + 1);
|
||||
line = strcat(line, ap_line);
|
||||
|
||||
case '&':
|
||||
curr_cmd->sep_next = AND_SEP;
|
||||
i++;
|
||||
tmp++;
|
||||
break;
|
||||
line_size = strlen(line);
|
||||
|
||||
case '|':
|
||||
curr_cmd->sep_next = OR_SEP;
|
||||
i++;
|
||||
tmp++;
|
||||
break;
|
||||
}
|
||||
free(ap_line);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp[0] == ' ')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
}
|
||||
i = j;
|
||||
|
||||
if (curr_pipe->args[0] != NULL)
|
||||
{
|
||||
if (strcmp(curr_pipe->args[0], "!") == 0)
|
||||
{
|
||||
curr_cmd->stat.invert = true;
|
||||
}
|
||||
}
|
||||
|
||||
cmds_p *next = new_cmd();
|
||||
|
||||
curr_cmd->next = next;
|
||||
|
||||
curr_cmd = curr_cmd->next;
|
||||
|
||||
curr_pipe = curr_cmd->pipe;
|
||||
}
|
||||
else if (line[i] == '|')
|
||||
{
|
||||
if (line[i - 1] != ' ')
|
||||
{
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
|
||||
}
|
||||
else
|
||||
tmp++;
|
||||
|
||||
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
|
||||
curr_pipe->args[curr_pipe->args_am] = NULL;
|
||||
|
||||
if (tmp[0] == ' ')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (curr_pipe->args[0] != NULL)
|
||||
{
|
||||
if (strcmp(curr_pipe->args[0], "!") == 0)
|
||||
{
|
||||
curr_cmd->stat.invert = true;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_pipe *next = new_cmd_pipe();
|
||||
|
||||
curr_pipe->next = next;
|
||||
curr_cmd->pipes_am++;
|
||||
curr_pipe = curr_pipe->next;
|
||||
}
|
||||
else if (line[i] == '>' || line[i] == '<')
|
||||
{
|
||||
int flags = 0;
|
||||
int f = 0;
|
||||
|
||||
if (line[i] == '>' && line[i + 1] == '>')
|
||||
{
|
||||
flags = O_CREAT | O_APPEND | O_WRONLY;
|
||||
i++;
|
||||
tmp++;
|
||||
f = 0;
|
||||
}
|
||||
else if (line[i] == '>')
|
||||
{
|
||||
flags = O_CREAT | O_TRUNC | O_WRONLY;
|
||||
f = 0;
|
||||
}
|
||||
else if (line[i] == '<' && line[i + 1] == '>')
|
||||
{
|
||||
flags = O_CREAT | O_RDWR;
|
||||
i++;
|
||||
tmp++;
|
||||
f = 1;
|
||||
}
|
||||
else if (line[i] == '<')
|
||||
{
|
||||
flags = O_RDONLY;
|
||||
f = 2;
|
||||
}
|
||||
|
||||
i++;
|
||||
tmp++;
|
||||
|
||||
if (line[i] == ' ')
|
||||
{
|
||||
i++;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
int j = i;
|
||||
for (; j < line_size; j++)
|
||||
if (line[j] == ' ' || line[j] == '|' || line[j] == '&' || line[j] == ';')
|
||||
break;
|
||||
|
||||
free_tmp[j] = '\0';
|
||||
|
||||
if (tmp[0] == '"')
|
||||
tmp++;
|
||||
if (free_tmp[j - 1] == '"')
|
||||
free_tmp[j - 1] = '\0';
|
||||
|
||||
int ffd;
|
||||
if ((ffd = open(tmp, flags)) < 0)
|
||||
{
|
||||
perror("file redirection: open");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f == 0)
|
||||
curr_pipe->pipefd[1] = ffd;
|
||||
else if (f == 1)
|
||||
for (int k = 0; k < 2; k++)
|
||||
curr_pipe->pipefd[k] = ffd;
|
||||
else if (f == 2)
|
||||
curr_pipe->pipefd[0] = ffd;
|
||||
|
||||
tmp += j - i + 1;
|
||||
i = j;
|
||||
}
|
||||
else if (line[i] == '$')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
int j = i;
|
||||
|
||||
for (; j < line_size; j++)
|
||||
if (line[j] == ' ' || line[j] == ';' || line[j] == '&' || line[j] == '|' || line[j] == '>' || line[j] == '<')
|
||||
break;
|
||||
|
||||
free_tmp[j] = '\0';
|
||||
|
||||
char *msg = NULL;
|
||||
|
||||
for (int k = 0; k < curr_cmd->envs_am; k++)
|
||||
if (strncmp(curr_cmd->envs[k], tmp, strlen(tmp)) == 0)
|
||||
msg = strchr(curr_cmd->envs[k], '=') + 1;
|
||||
|
||||
if (msg == NULL)
|
||||
{
|
||||
msg = get_env_var(tmp);
|
||||
|
||||
if (msg == NULL)
|
||||
msg = strdup("");
|
||||
}
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, msg);
|
||||
|
||||
tmp += j - i + 1;
|
||||
i = j;
|
||||
}
|
||||
else if (line[i] == ' ')
|
||||
{
|
||||
free_tmp[i] = '\0';
|
||||
|
||||
if (curr_cmd->pipe->args[0] == NULL && strchr(tmp, '='))
|
||||
{
|
||||
append_to_str_arr(&curr_cmd->envs, &curr_cmd->envs_am, tmp);
|
||||
tmp += strlen(curr_cmd->envs[curr_cmd->envs_am - 1]) + 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char *ap_string = trim_string(tmp, false), **exp = calloc(0, sizeof(char *));
|
||||
|
||||
int sz = expand_wildcatrd(&exp, ap_string);
|
||||
|
||||
for (int l = 0; l < sz; l++)
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, exp[l]);
|
||||
|
||||
tmp += strlen(ap_string) + 1;
|
||||
}
|
||||
else if (line[i] == '#')
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (tmp[0] == ' ')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp[0] != '\0' && tmp[0] != '#')
|
||||
else if (line[i] == ';' || (line[i] == '&' && line[i + 1] == '&') || (line[i] == '|' && line[i + 1] == '|'))
|
||||
{
|
||||
if (tmp[strlen(tmp) - 1] != '"')
|
||||
{
|
||||
char *ap_string = trim_string(tmp, false), **exp = calloc(0, sizeof(char *));
|
||||
free_tmp[i] = '\0';
|
||||
if (line[i - 1] != ' ')
|
||||
{
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
|
||||
}
|
||||
else
|
||||
tmp++;
|
||||
|
||||
int sz = expand_wildcatrd(&exp, ap_string);
|
||||
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
|
||||
curr_pipe->args[curr_pipe->args_am] = NULL;
|
||||
|
||||
for (int l = 0; l < sz; l++)
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, exp[l]);
|
||||
}
|
||||
else
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
}
|
||||
switch (line[i])
|
||||
{
|
||||
case ';':
|
||||
curr_cmd->sep_next = SEMICOLON_SEP;
|
||||
break;
|
||||
|
||||
if (curr_pipe->args[0] != NULL)
|
||||
{
|
||||
case '&':
|
||||
curr_cmd->sep_next = AND_SEP;
|
||||
i++;
|
||||
tmp++;
|
||||
break;
|
||||
|
||||
case '|':
|
||||
curr_cmd->sep_next = OR_SEP;
|
||||
i++;
|
||||
tmp++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp[0] == ' ')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (curr_pipe->args[0] != NULL)
|
||||
{
|
||||
if (strcmp(curr_pipe->args[0], "!") == 0)
|
||||
{
|
||||
curr_cmd->stat.invert = true;
|
||||
curr_cmd->stat.invert = true;
|
||||
}
|
||||
}
|
||||
|
||||
cmds_p *next = new_cmd();
|
||||
|
||||
curr_cmd->next = next;
|
||||
|
||||
curr_cmd = curr_cmd->next;
|
||||
|
||||
curr_pipe = curr_cmd->pipe;
|
||||
}
|
||||
|
||||
free(free_tmp);
|
||||
|
||||
if (curr_pipe->args[curr_pipe->args_am] != NULL)
|
||||
else if (line[i] == '|')
|
||||
{
|
||||
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
|
||||
curr_pipe->args[curr_pipe->args_am] = NULL;
|
||||
}
|
||||
if (curr_pipe->pipefd[1] < 0)
|
||||
curr_pipe->pipefd[1] = STDOUT_FILENO;
|
||||
if (line[i - 1] != ' ')
|
||||
{
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
|
||||
}
|
||||
else
|
||||
tmp++;
|
||||
|
||||
return coms;
|
||||
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
|
||||
curr_pipe->args[curr_pipe->args_am] = NULL;
|
||||
|
||||
if (tmp[0] == ' ')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (curr_pipe->args[0] != NULL)
|
||||
{
|
||||
if (strcmp(curr_pipe->args[0], "!") == 0)
|
||||
{
|
||||
curr_cmd->stat.invert = true;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_pipe *next = new_cmd_pipe();
|
||||
|
||||
curr_pipe->next = next;
|
||||
curr_cmd->pipes_am++;
|
||||
curr_pipe = curr_pipe->next;
|
||||
}
|
||||
else if (line[i] == '>' || line[i] == '<')
|
||||
{
|
||||
int flags = 0;
|
||||
int f = 0;
|
||||
|
||||
if (line[i] == '>' && line[i + 1] == '>')
|
||||
{
|
||||
flags = O_CREAT | O_APPEND | O_WRONLY;
|
||||
i++;
|
||||
tmp++;
|
||||
f = 0;
|
||||
}
|
||||
else if (line[i] == '>')
|
||||
{
|
||||
flags = O_CREAT | O_TRUNC | O_WRONLY;
|
||||
f = 0;
|
||||
}
|
||||
else if (line[i] == '<' && line[i + 1] == '>')
|
||||
{
|
||||
flags = O_CREAT | O_RDWR;
|
||||
i++;
|
||||
tmp++;
|
||||
f = 1;
|
||||
}
|
||||
else if (line[i] == '<')
|
||||
{
|
||||
flags = O_RDONLY;
|
||||
f = 2;
|
||||
}
|
||||
|
||||
i++;
|
||||
tmp++;
|
||||
|
||||
if (line[i] == ' ')
|
||||
{
|
||||
i++;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
int j = i;
|
||||
for (; j < line_size; j++)
|
||||
if (line[j] == ' ' || line[j] == '|' || line[j] == '&' || line[j] == ';')
|
||||
break;
|
||||
|
||||
free_tmp[j] = '\0';
|
||||
|
||||
if (tmp[0] == '"')
|
||||
tmp++;
|
||||
if (free_tmp[j - 1] == '"')
|
||||
free_tmp[j - 1] = '\0';
|
||||
|
||||
int ffd;
|
||||
if ((ffd = open(tmp, flags)) < 0)
|
||||
{
|
||||
perror("file redirection: open");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f == 0)
|
||||
curr_pipe->pipefd[1] = ffd;
|
||||
else if (f == 1)
|
||||
for (int k = 0; k < 2; k++)
|
||||
curr_pipe->pipefd[k] = ffd;
|
||||
else if (f == 2)
|
||||
curr_pipe->pipefd[0] = ffd;
|
||||
|
||||
tmp += j - i + 1;
|
||||
i = j;
|
||||
}
|
||||
else if (line[i] == '$')
|
||||
{
|
||||
tmp++;
|
||||
i++;
|
||||
int j = i;
|
||||
|
||||
for (; j < line_size; j++)
|
||||
if (line[j] == ' ' || line[j] == ';' || line[j] == '&' || line[j] == '|' || line[j] == '>' || line[j] == '<')
|
||||
break;
|
||||
|
||||
free_tmp[j] = '\0';
|
||||
|
||||
char *msg = NULL;
|
||||
|
||||
for (int k = 0; k < curr_cmd->envs_am; k++)
|
||||
if (strncmp(curr_cmd->envs[k], tmp, strlen(tmp)) == 0)
|
||||
msg = strchr(curr_cmd->envs[k], '=') + 1;
|
||||
|
||||
if (msg == NULL)
|
||||
{
|
||||
msg = get_env_var(tmp);
|
||||
|
||||
if (msg == NULL)
|
||||
msg = strdup("");
|
||||
}
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, msg);
|
||||
|
||||
tmp += j - i + 1;
|
||||
i = j;
|
||||
}
|
||||
else if (line[i] == ' ')
|
||||
{
|
||||
free_tmp[i] = '\0';
|
||||
|
||||
if (curr_cmd->pipe->args[0] == NULL && strchr(tmp, '='))
|
||||
{
|
||||
append_to_str_arr(&curr_cmd->envs, &curr_cmd->envs_am, tmp);
|
||||
tmp += strlen(curr_cmd->envs[curr_cmd->envs_am - 1]) + 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char *ap_string = trim_string(tmp, false), **exp = calloc(0, sizeof(char *));
|
||||
|
||||
int sz = expand_wildcatrd(&exp, ap_string);
|
||||
|
||||
for (int l = 0; l < sz; l++)
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, exp[l]);
|
||||
|
||||
tmp += strlen(ap_string) + 1;
|
||||
}
|
||||
else if (line[i] == '#')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp[0] != '\0' && tmp[0] != '#')
|
||||
{
|
||||
if (tmp[strlen(tmp) - 1] != '"')
|
||||
{
|
||||
char *ap_string = trim_string(tmp, false), **exp = calloc(0, sizeof(char *));
|
||||
|
||||
int sz = expand_wildcatrd(&exp, ap_string);
|
||||
|
||||
for (int l = 0; l < sz; l++)
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, exp[l]);
|
||||
}
|
||||
else
|
||||
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
|
||||
}
|
||||
|
||||
if (curr_pipe->args[0] != NULL)
|
||||
{
|
||||
if (strcmp(curr_pipe->args[0], "!") == 0)
|
||||
{
|
||||
curr_cmd->stat.invert = true;
|
||||
}
|
||||
}
|
||||
|
||||
free(free_tmp);
|
||||
|
||||
if (curr_pipe->args[curr_pipe->args_am] != NULL)
|
||||
{
|
||||
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
|
||||
curr_pipe->args[curr_pipe->args_am] = NULL;
|
||||
}
|
||||
if (curr_pipe->pipefd[1] < 0)
|
||||
curr_pipe->pipefd[1] = STDOUT_FILENO;
|
||||
|
||||
return coms;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,20 +322,20 @@ cmds_p *process_line(char *line)
|
||||
*/
|
||||
int expand_wildcatrd(char ***arr, char *input)
|
||||
{
|
||||
ssize_t size = 0;
|
||||
ssize_t size = 0;
|
||||
|
||||
if (strchr(input, '*') || strchr(input, '~') || strchr(input, '?'))
|
||||
{
|
||||
glob_t globbuf;
|
||||
int t = glob(input, GLOB_TILDE, NULL, &globbuf);
|
||||
if (t != 0)
|
||||
perror("Glob");
|
||||
if (strchr(input, '*') || strchr(input, '~') || strchr(input, '?'))
|
||||
{
|
||||
glob_t globbuf;
|
||||
int t = glob(input, GLOB_TILDE, NULL, &globbuf);
|
||||
if (t != 0)
|
||||
perror("Glob");
|
||||
|
||||
for (int j = 0; j < globbuf.gl_pathc; j++)
|
||||
append_to_str_arr(arr, &size, globbuf.gl_pathv[j]);
|
||||
}
|
||||
else
|
||||
append_to_str_arr(arr, &size, input);
|
||||
for (int j = 0; j < globbuf.gl_pathc; j++)
|
||||
append_to_str_arr(arr, &size, globbuf.gl_pathv[j]);
|
||||
}
|
||||
else
|
||||
append_to_str_arr(arr, &size, input);
|
||||
|
||||
return size;
|
||||
return size;
|
||||
}
|
32
src/main.c
32
src/main.c
@ -15,36 +15,36 @@ t_ init_term();
|
||||
// Main
|
||||
int main()
|
||||
{
|
||||
term = init_term();
|
||||
term = init_term();
|
||||
|
||||
while (1)
|
||||
{
|
||||
process_command();
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
process_command();
|
||||
}
|
||||
}
|
||||
|
||||
// Init
|
||||
t_ init_term()
|
||||
{
|
||||
// Entering raw mode
|
||||
change_mode(1);
|
||||
// Entering raw mode
|
||||
change_mode(1);
|
||||
|
||||
// Init history
|
||||
init_history();
|
||||
// Init history
|
||||
init_history();
|
||||
|
||||
term.last_status = 0;
|
||||
term.last_status = 0;
|
||||
|
||||
// Disable Ctrl+C default behaviour for shell
|
||||
signal(SIGINT, SIG_IGN);
|
||||
// Disable Ctrl+C default behaviour for shell
|
||||
signal(SIGINT, SIG_IGN);
|
||||
|
||||
// Set up function to run on shell exit
|
||||
atexit(exit_shell);
|
||||
// Set up function to run on shell exit
|
||||
atexit(exit_shell);
|
||||
|
||||
return term;
|
||||
return term;
|
||||
}
|
||||
|
||||
// Exit
|
||||
void exit_shell()
|
||||
{
|
||||
change_mode(0);
|
||||
change_mode(0);
|
||||
}
|
12
src/output.c
12
src/output.c
@ -11,13 +11,13 @@
|
||||
*/
|
||||
size_t append_to_buff(char **buff, size_t *buff_size, char *ap, size_t ap_size)
|
||||
{
|
||||
*buff = realloc(*buff, *buff_size + ap_size);
|
||||
memcpy(*buff + *buff_size - 1, ap, ap_size);
|
||||
*buff = realloc(*buff, *buff_size + ap_size);
|
||||
memcpy(*buff + *buff_size - 1, ap, ap_size);
|
||||
|
||||
*buff_size += ap_size;
|
||||
(*buff)[*buff_size - 1] = '\0';
|
||||
*buff_size += ap_size;
|
||||
(*buff)[*buff_size - 1] = '\0';
|
||||
|
||||
return *buff_size;
|
||||
return *buff_size;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,5 +28,5 @@ size_t append_to_buff(char **buff, size_t *buff_size, char *ap, size_t ap_size)
|
||||
*/
|
||||
void print_str(char *buff, size_t size)
|
||||
{
|
||||
write(STDOUT_FILENO, buff, size);
|
||||
write(STDOUT_FILENO, buff, size);
|
||||
}
|
120
src/prompt.c
120
src/prompt.c
@ -8,27 +8,27 @@
|
||||
*/
|
||||
char *get_ip_addr()
|
||||
{
|
||||
struct ifaddrs *host, *tmp;
|
||||
getifaddrs(&host);
|
||||
tmp = host;
|
||||
char *ip = NULL;
|
||||
struct ifaddrs *host, *tmp;
|
||||
getifaddrs(&host);
|
||||
tmp = host;
|
||||
char *ip = NULL;
|
||||
|
||||
while (tmp)
|
||||
while (tmp)
|
||||
{
|
||||
if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
|
||||
ip = inet_ntoa(pAddr->sin_addr);
|
||||
if (strncmp(ip, "127", 3) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = tmp->ifa_next;
|
||||
struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
|
||||
ip = inet_ntoa(pAddr->sin_addr);
|
||||
if (strncmp(ip, "127", 3) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
freeifaddrs(host);
|
||||
tmp = tmp->ifa_next;
|
||||
}
|
||||
|
||||
return ip;
|
||||
freeifaddrs(host);
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,54 +38,54 @@ char *get_ip_addr()
|
||||
*/
|
||||
char *compose_prompt()
|
||||
{
|
||||
// New line
|
||||
char *prompt = strdup("");
|
||||
// New line
|
||||
char *prompt = strdup("");
|
||||
|
||||
// Username
|
||||
char *username = strdup(getlogin());
|
||||
if (username == NULL)
|
||||
username = "none";
|
||||
prompt = realloc(prompt, strlen(prompt) + strlen("\033[97;44m") + strlen(username) + 2);
|
||||
prompt = strcat(prompt, "\033[97;44m");
|
||||
prompt = strcat(prompt, username);
|
||||
// Username
|
||||
char *username = strdup(getlogin());
|
||||
if (username == NULL)
|
||||
username = "none";
|
||||
prompt = realloc(prompt, strlen(prompt) + strlen("\033[97;44m") + strlen(username) + 2);
|
||||
prompt = strcat(prompt, "\033[97;44m");
|
||||
prompt = strcat(prompt, username);
|
||||
|
||||
// Current host ip
|
||||
char *ip = get_ip_addr();
|
||||
if (ip == NULL)
|
||||
ip = "none";
|
||||
prompt = realloc(prompt, strlen(prompt) + 1 + strlen(ip) + strlen("\033[39m") + strlen("\033[0m") + 2);
|
||||
prompt = strcat(prompt, "@");
|
||||
prompt = strcat(prompt, ip);
|
||||
prompt = strcat(prompt, "\033[39m");
|
||||
prompt = strcat(prompt, "\033[0m");
|
||||
prompt = strcat(prompt, ":");
|
||||
// Current host ip
|
||||
char *ip = get_ip_addr();
|
||||
if (ip == NULL)
|
||||
ip = "none";
|
||||
prompt = realloc(prompt, strlen(prompt) + 1 + strlen(ip) + strlen("\033[39m") + strlen("\033[0m") + 2);
|
||||
prompt = strcat(prompt, "@");
|
||||
prompt = strcat(prompt, ip);
|
||||
prompt = strcat(prompt, "\033[39m");
|
||||
prompt = strcat(prompt, "\033[0m");
|
||||
prompt = strcat(prompt, ":");
|
||||
|
||||
// Current path
|
||||
char *full_path = get_curr_dir_name();
|
||||
prompt = realloc(prompt, strlen(prompt) + strlen("\033[92;1m") + strlen("\033[0m") + strlen(full_path) + 2);
|
||||
prompt = strcat(prompt, "\033[92;1m");
|
||||
prompt = strcat(prompt, full_path);
|
||||
prompt = strcat(prompt, "\033[0m");
|
||||
free(full_path);
|
||||
// Current path
|
||||
char *full_path = get_curr_dir_name();
|
||||
prompt = realloc(prompt, strlen(prompt) + strlen("\033[92;1m") + strlen("\033[0m") + strlen(full_path) + 2);
|
||||
prompt = strcat(prompt, "\033[92;1m");
|
||||
prompt = strcat(prompt, full_path);
|
||||
prompt = strcat(prompt, "\033[0m");
|
||||
free(full_path);
|
||||
|
||||
// Previous status
|
||||
if (term.last_status != 0)
|
||||
{
|
||||
char *status = malloc(snprintf(NULL, 0, " \033[91m%d\033[39m", term.last_status));
|
||||
sprintf(status, " \033[91m%d\033[39m", term.last_status);
|
||||
prompt = realloc(prompt, strlen(prompt) + strlen(status) + 1);
|
||||
prompt = strcat(prompt, status);
|
||||
free(status);
|
||||
}
|
||||
// Previous status
|
||||
if (term.last_status != 0)
|
||||
{
|
||||
char *status = malloc(snprintf(NULL, 0, " \033[91m%d\033[39m", term.last_status));
|
||||
sprintf(status, " \033[91m%d\033[39m", term.last_status);
|
||||
prompt = realloc(prompt, strlen(prompt) + strlen(status) + 1);
|
||||
prompt = strcat(prompt, status);
|
||||
free(status);
|
||||
}
|
||||
|
||||
// Permissions specific character before user input
|
||||
prompt = realloc(prompt, strlen(prompt) + 4);
|
||||
if (getuid() == 0)
|
||||
{
|
||||
prompt = strcat(prompt, "\n# ");
|
||||
}
|
||||
else
|
||||
prompt = strcat(prompt, "\n% ");
|
||||
// Permissions specific character before user input
|
||||
prompt = realloc(prompt, strlen(prompt) + 4);
|
||||
if (getuid() == 0)
|
||||
{
|
||||
prompt = strcat(prompt, "\n# ");
|
||||
}
|
||||
else
|
||||
prompt = strcat(prompt, "\n% ");
|
||||
|
||||
return prompt;
|
||||
return prompt;
|
||||
}
|
138
src/shell.c
138
src/shell.c
@ -8,50 +8,50 @@
|
||||
*/
|
||||
void process_command()
|
||||
{
|
||||
char *prompt = compose_prompt();
|
||||
print_str(prompt, strlen(prompt));
|
||||
char *prompt = compose_prompt();
|
||||
print_str(prompt, strlen(prompt));
|
||||
|
||||
char *line = read_line();
|
||||
char *line = read_line();
|
||||
|
||||
char *tmp = trim_string(line, false);
|
||||
free(line);
|
||||
line = tmp;
|
||||
char *tmp = trim_string(line, false);
|
||||
free(line);
|
||||
line = tmp;
|
||||
|
||||
cmds_p *coms = process_line(line);
|
||||
cmds_p *coms = process_line(line);
|
||||
|
||||
cmds_p *curr = coms;
|
||||
int status = 0;
|
||||
while (curr != NULL)
|
||||
cmds_p *curr = coms;
|
||||
int status = 0;
|
||||
while (curr != NULL)
|
||||
{
|
||||
status = execute_with_pipes(curr);
|
||||
|
||||
if (curr->stat.invert)
|
||||
{
|
||||
status = execute_with_pipes(curr);
|
||||
|
||||
if (curr->stat.invert)
|
||||
{
|
||||
if (status == 0)
|
||||
status = 1;
|
||||
else
|
||||
status = 0;
|
||||
}
|
||||
|
||||
curr->stat.s = term.last_status = status;
|
||||
|
||||
if (curr->sep_next == AND_SEP)
|
||||
{
|
||||
if (term.last_status != 0)
|
||||
break;
|
||||
}
|
||||
else if (curr->sep_next == OR_SEP)
|
||||
{
|
||||
if (term.last_status == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
curr = curr->next;
|
||||
if (status == 0)
|
||||
status = 1;
|
||||
else
|
||||
status = 0;
|
||||
}
|
||||
|
||||
free(line);
|
||||
free(prompt);
|
||||
free_cmds_p(coms);
|
||||
curr->stat.s = term.last_status = status;
|
||||
|
||||
if (curr->sep_next == AND_SEP)
|
||||
{
|
||||
if (term.last_status != 0)
|
||||
break;
|
||||
}
|
||||
else if (curr->sep_next == OR_SEP)
|
||||
{
|
||||
if (term.last_status == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
free(line);
|
||||
free(prompt);
|
||||
free_cmds_p(coms);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,20 +61,20 @@ void process_command()
|
||||
*/
|
||||
cmds_p *new_cmd()
|
||||
{
|
||||
cmds_p *new = malloc(sizeof(cmds_p));
|
||||
cmds_p *new = malloc(sizeof(cmds_p));
|
||||
|
||||
new->pipe = new_cmd_pipe();
|
||||
new->pipes_am = 1;
|
||||
new->pipe = new_cmd_pipe();
|
||||
new->pipes_am = 1;
|
||||
|
||||
new->envs = calloc(0, sizeof(char *));
|
||||
new->envs_am = 0;
|
||||
new->envs = calloc(0, sizeof(char *));
|
||||
new->envs_am = 0;
|
||||
|
||||
new->stat.s = 0;
|
||||
new->sep_next = NO_SEP;
|
||||
new->stat.invert = false;
|
||||
new->next = NULL;
|
||||
new->stat.s = 0;
|
||||
new->sep_next = NO_SEP;
|
||||
new->stat.invert = false;
|
||||
new->next = NULL;
|
||||
|
||||
return new;
|
||||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,38 +84,38 @@ cmds_p *new_cmd()
|
||||
*/
|
||||
cmd_pipe *new_cmd_pipe()
|
||||
{
|
||||
cmd_pipe *new = malloc(sizeof(cmd_pipe));
|
||||
new->args = calloc(0, sizeof(char *));
|
||||
new->args_am = 0;
|
||||
new->next = NULL;
|
||||
new->pipefd[0] = new->pipefd[1] = -1;
|
||||
cmd_pipe *new = malloc(sizeof(cmd_pipe));
|
||||
new->args = calloc(0, sizeof(char *));
|
||||
new->args_am = 0;
|
||||
new->next = NULL;
|
||||
new->pipefd[0] = new->pipefd[1] = -1;
|
||||
|
||||
return new;
|
||||
return new;
|
||||
}
|
||||
|
||||
void free_cmds_p(cmds_p *root)
|
||||
{
|
||||
if (root != NULL)
|
||||
{
|
||||
if (root->pipe != NULL)
|
||||
free_cmd_pipe(root->pipe);
|
||||
if (root != NULL)
|
||||
{
|
||||
if (root->pipe != NULL)
|
||||
free_cmd_pipe(root->pipe);
|
||||
|
||||
if (root->next != NULL)
|
||||
free_cmds_p(root->next);
|
||||
if (root->next != NULL)
|
||||
free_cmds_p(root->next);
|
||||
|
||||
free(root);
|
||||
}
|
||||
return;
|
||||
free(root);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void free_cmd_pipe(cmd_pipe *root)
|
||||
{
|
||||
if (root != NULL)
|
||||
{
|
||||
if (root->next != NULL)
|
||||
free_cmd_pipe(root->next);
|
||||
if (root != NULL)
|
||||
{
|
||||
if (root->next != NULL)
|
||||
free_cmd_pipe(root->next);
|
||||
|
||||
free(root);
|
||||
}
|
||||
return;
|
||||
free(root);
|
||||
}
|
||||
return;
|
||||
}
|
180
src/tree.c
180
src/tree.c
@ -7,15 +7,15 @@
|
||||
*/
|
||||
struct tree_node *get_new_node()
|
||||
{
|
||||
struct tree_node *node = malloc(sizeof(struct tree_node));
|
||||
node->is_leaf = 0;
|
||||
struct tree_node *node = malloc(sizeof(struct tree_node));
|
||||
node->is_leaf = 0;
|
||||
|
||||
for (int i = 0; i < ALPHABET_SIZE; i++)
|
||||
{
|
||||
node->child[i] = NULL;
|
||||
}
|
||||
for (int i = 0; i < ALPHABET_SIZE; i++)
|
||||
{
|
||||
node->child[i] = NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -26,20 +26,20 @@ struct tree_node *get_new_node()
|
||||
*/
|
||||
void insert_tree(struct tree_node *root, char *key)
|
||||
{
|
||||
struct tree_node *current = root;
|
||||
struct tree_node *current = root;
|
||||
|
||||
for (int i = 0; i < strlen(key); i++)
|
||||
{
|
||||
char index = key[i];
|
||||
if (current->child[index] == NULL)
|
||||
{
|
||||
current->child[index] = get_new_node();
|
||||
}
|
||||
for (int i = 0; i < strlen(key); i++)
|
||||
{
|
||||
char index = key[i];
|
||||
if (current->child[index] == NULL)
|
||||
{
|
||||
current->child[index] = get_new_node();
|
||||
}
|
||||
|
||||
current = current->child[index];
|
||||
}
|
||||
current = current->child[index];
|
||||
}
|
||||
|
||||
current->is_leaf = 1;
|
||||
current->is_leaf = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,19 +49,19 @@ void insert_tree(struct tree_node *root, char *key)
|
||||
*/
|
||||
void free_tree(struct tree_node *root)
|
||||
{
|
||||
if (root != NULL)
|
||||
if (root != NULL)
|
||||
{
|
||||
for (int i = 0; i < ALPHABET_SIZE; i++)
|
||||
{
|
||||
if (root->child[i] != NULL)
|
||||
{
|
||||
for (int i = 0; i < ALPHABET_SIZE; i++)
|
||||
{
|
||||
if (root->child[i] != NULL)
|
||||
{
|
||||
free_tree(root->child[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(root);
|
||||
free_tree(root->child[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
free(root);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,21 +73,21 @@ void free_tree(struct tree_node *root)
|
||||
*/
|
||||
int search_tree(struct tree_node *root, char *key)
|
||||
{
|
||||
struct tree_node *current = root;
|
||||
struct tree_node *current = root;
|
||||
|
||||
for (int i = 0; i < strlen(key); i++)
|
||||
{
|
||||
char index = key[i];
|
||||
for (int i = 0; i < strlen(key); i++)
|
||||
{
|
||||
char index = key[i];
|
||||
|
||||
if (current->child[index] == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (current->child[index] == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
current = current->child[index];
|
||||
}
|
||||
current = current->child[index];
|
||||
}
|
||||
|
||||
return (current != NULL && current->is_leaf);
|
||||
return (current != NULL && current->is_leaf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,11 +98,11 @@ int search_tree(struct tree_node *root, char *key)
|
||||
*/
|
||||
int is_last_node(struct tree_node *root)
|
||||
{
|
||||
for (int i = 0; i < ALPHABET_SIZE; i++)
|
||||
if (root->child[i] != NULL)
|
||||
return 0;
|
||||
for (int i = 0; i < ALPHABET_SIZE; i++)
|
||||
if (root->child[i] != NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,48 +115,48 @@ int is_last_node(struct tree_node *root)
|
||||
*/
|
||||
ssize_t list_strings_containing(struct tree_node *root, char *key, char ***strings)
|
||||
{
|
||||
ssize_t amount = 0;
|
||||
ssize_t amount = 0;
|
||||
|
||||
free(*strings);
|
||||
free(*strings);
|
||||
|
||||
*strings = calloc(amount, sizeof(char *));
|
||||
*strings = calloc(amount, sizeof(char *));
|
||||
|
||||
struct tree_node *current = root;
|
||||
struct tree_node *current = root;
|
||||
|
||||
for (int level = 0; level < strlen(key); level++)
|
||||
{
|
||||
int index = key[level];
|
||||
for (int level = 0; level < strlen(key); level++)
|
||||
{
|
||||
int index = key[level];
|
||||
|
||||
if (current->child[index] == NULL)
|
||||
return amount;
|
||||
if (current->child[index] == NULL)
|
||||
return amount;
|
||||
|
||||
current = current->child[index];
|
||||
}
|
||||
current = current->child[index];
|
||||
}
|
||||
|
||||
int key_presents = current->is_leaf;
|
||||
int key_presents = current->is_leaf;
|
||||
|
||||
int is_last = is_last_node(current);
|
||||
int is_last = is_last_node(current);
|
||||
|
||||
if (key_presents && is_last)
|
||||
{
|
||||
amount++;
|
||||
*strings = (char **)realloc(*strings, amount * sizeof(char *));
|
||||
(*strings)[0] = strdup(key);
|
||||
return amount;
|
||||
}
|
||||
if (key_presents && is_last)
|
||||
{
|
||||
amount++;
|
||||
*strings = (char **)realloc(*strings, amount * sizeof(char *));
|
||||
(*strings)[0] = strdup(key);
|
||||
return amount;
|
||||
}
|
||||
|
||||
if (is_last == 0)
|
||||
{
|
||||
char *prefix = strdup(key);
|
||||
if (is_last == 0)
|
||||
{
|
||||
char *prefix = strdup(key);
|
||||
|
||||
get_all_substrings(current, &amount, &prefix, strings);
|
||||
get_all_substrings(current, &amount, &prefix, strings);
|
||||
|
||||
free(prefix);
|
||||
free(prefix);
|
||||
|
||||
return amount;
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,26 +169,26 @@ ssize_t list_strings_containing(struct tree_node *root, char *key, char ***strin
|
||||
*/
|
||||
void get_all_substrings(struct tree_node *root, ssize_t *amount, char **curr_prefix, char ***strings)
|
||||
{
|
||||
if (root->is_leaf)
|
||||
{
|
||||
(*amount)++;
|
||||
*strings = (char **)realloc(*strings, *amount * sizeof(char *));
|
||||
(*strings)[*amount - 1] = strdup(*curr_prefix);
|
||||
}
|
||||
if (root->is_leaf)
|
||||
{
|
||||
(*amount)++;
|
||||
*strings = (char **)realloc(*strings, *amount * sizeof(char *));
|
||||
(*strings)[*amount - 1] = strdup(*curr_prefix);
|
||||
}
|
||||
|
||||
if (is_last_node(root))
|
||||
return;
|
||||
if (is_last_node(root))
|
||||
return;
|
||||
|
||||
for (int index = 0; index < ALPHABET_SIZE; index++)
|
||||
{
|
||||
if (root->child[index] != NULL)
|
||||
{
|
||||
*curr_prefix = realloc(*curr_prefix, strlen(*curr_prefix) + 2);
|
||||
*curr_prefix = strncat(*curr_prefix, (char *)(&index), 1);
|
||||
for (int index = 0; index < ALPHABET_SIZE; index++)
|
||||
{
|
||||
if (root->child[index] != NULL)
|
||||
{
|
||||
*curr_prefix = realloc(*curr_prefix, strlen(*curr_prefix) + 2);
|
||||
*curr_prefix = strncat(*curr_prefix, (char *)(&index), 1);
|
||||
|
||||
get_all_substrings(root->child[index], amount, curr_prefix, strings);
|
||||
get_all_substrings(root->child[index], amount, curr_prefix, strings);
|
||||
|
||||
(*curr_prefix)[strlen(*curr_prefix) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
(*curr_prefix)[strlen(*curr_prefix) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
238
src/utils.c
238
src/utils.c
@ -9,18 +9,18 @@
|
||||
*/
|
||||
void append_to_pos(char **str, int pos, char ch)
|
||||
{
|
||||
size_t len = strlen(*str);
|
||||
if (pos <= len + 1)
|
||||
{
|
||||
*str = realloc(*str, len + 2);
|
||||
size_t len = strlen(*str);
|
||||
if (pos <= len + 1)
|
||||
{
|
||||
*str = realloc(*str, len + 2);
|
||||
|
||||
for (int i = len; i >= pos; i--)
|
||||
{
|
||||
(*str)[i + 1] = (*str)[i];
|
||||
}
|
||||
(*str)[pos] = ch;
|
||||
(*str)[len + 1] = '\0';
|
||||
}
|
||||
for (int i = len; i >= pos; i--)
|
||||
{
|
||||
(*str)[i + 1] = (*str)[i];
|
||||
}
|
||||
(*str)[pos] = ch;
|
||||
(*str)[len + 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -31,15 +31,15 @@ void append_to_pos(char **str, int pos, char ch)
|
||||
*/
|
||||
void remove_on_pos(char **str, int pos)
|
||||
{
|
||||
size_t len = strlen(*str);
|
||||
if (pos <= len)
|
||||
{
|
||||
for (int i = pos - 1; i < len; i++)
|
||||
(*str)[i] = (*str)[i + 1];
|
||||
size_t len = strlen(*str);
|
||||
if (pos <= len)
|
||||
{
|
||||
for (int i = pos - 1; i < len; i++)
|
||||
(*str)[i] = (*str)[i + 1];
|
||||
|
||||
(*str)[len] = '\0';
|
||||
*str = realloc(*str, len);
|
||||
}
|
||||
(*str)[len] = '\0';
|
||||
*str = realloc(*str, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,23 +52,23 @@ void remove_on_pos(char **str, int pos)
|
||||
*/
|
||||
int sep_string(char *line, char ***toks, char *sep)
|
||||
{
|
||||
free(*toks);
|
||||
char *tmp_line = strdup(line);
|
||||
char *free_tmp_line = tmp_line;
|
||||
int n = 0;
|
||||
*toks = calloc(n, sizeof(char *));
|
||||
free(*toks);
|
||||
char *tmp_line = strdup(line);
|
||||
char *free_tmp_line = tmp_line;
|
||||
int n = 0;
|
||||
*toks = calloc(n, sizeof(char *));
|
||||
|
||||
char *tmp = NULL;
|
||||
while ((tmp = strsep(&tmp_line, sep)) != NULL)
|
||||
{
|
||||
n++;
|
||||
*toks = realloc(*toks, sizeof(char *) * n);
|
||||
(*toks)[n - 1] = strdup(tmp);
|
||||
}
|
||||
char *tmp = NULL;
|
||||
while ((tmp = strsep(&tmp_line, sep)) != NULL)
|
||||
{
|
||||
n++;
|
||||
*toks = realloc(*toks, sizeof(char *) * n);
|
||||
(*toks)[n - 1] = strdup(tmp);
|
||||
}
|
||||
|
||||
free(free_tmp_line);
|
||||
free(free_tmp_line);
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,22 +79,22 @@ int sep_string(char *line, char ***toks, char *sep)
|
||||
*/
|
||||
char *trim_string(char *str, bool leave_trailing_space)
|
||||
{
|
||||
char *tmp = strdup(str);
|
||||
while (tmp[0] == ' ')
|
||||
remove_on_pos(&tmp, 1);
|
||||
char *tmp = strdup(str);
|
||||
while (tmp[0] == ' ')
|
||||
remove_on_pos(&tmp, 1);
|
||||
|
||||
for (int i = 1; i < strlen(tmp); i++)
|
||||
if (tmp[i] == ' ' && tmp[i - 1] == ' ')
|
||||
{
|
||||
remove_on_pos(&tmp, i);
|
||||
i--;
|
||||
}
|
||||
for (int i = 1; i < strlen(tmp); i++)
|
||||
if (tmp[i] == ' ' && tmp[i - 1] == ' ')
|
||||
{
|
||||
remove_on_pos(&tmp, i);
|
||||
i--;
|
||||
}
|
||||
|
||||
if (!leave_trailing_space)
|
||||
if (tmp[strlen(tmp) - 1] == ' ' && tmp[strlen(tmp) - 2] == ' ')
|
||||
remove_on_pos(&tmp, strlen(tmp) - 1);
|
||||
if (!leave_trailing_space)
|
||||
if (tmp[strlen(tmp) - 1] == ' ' && tmp[strlen(tmp) - 2] == ' ')
|
||||
remove_on_pos(&tmp, strlen(tmp) - 1);
|
||||
|
||||
return tmp;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,10 +105,10 @@ char *trim_string(char *str, bool leave_trailing_space)
|
||||
*/
|
||||
void free_str_arr(char **arr, int sz)
|
||||
{
|
||||
if (arr[0] != NULL)
|
||||
for (int i = 0; i < sz; i++)
|
||||
free(arr[i]);
|
||||
free(arr);
|
||||
if (arr[0] != NULL)
|
||||
for (int i = 0; i < sz; i++)
|
||||
free(arr[i]);
|
||||
free(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,21 +122,21 @@ void free_str_arr(char **arr, int sz)
|
||||
*/
|
||||
char **slice_array(char **arr, int beg, int end, bool asc)
|
||||
{
|
||||
if (beg == -1)
|
||||
beg = 0;
|
||||
if (end == -1)
|
||||
end = get_null_term_arr_size(arr);
|
||||
if (beg == -1)
|
||||
beg = 0;
|
||||
if (end == -1)
|
||||
end = get_null_term_arr_size(arr);
|
||||
|
||||
char **new_arr = calloc(abs(end - beg), sizeof(char *));
|
||||
char **new_arr = calloc(abs(end - beg), sizeof(char *));
|
||||
|
||||
if (asc)
|
||||
for (int i = beg, j = 0; i < end; i++, j++)
|
||||
new_arr[j] = arr[i];
|
||||
else
|
||||
for (int i = end, j = 0; i > beg; i--, j++)
|
||||
new_arr[j] = arr[i];
|
||||
if (asc)
|
||||
for (int i = beg, j = 0; i < end; i++, j++)
|
||||
new_arr[j] = arr[i];
|
||||
else
|
||||
for (int i = end, j = 0; i > beg; i--, j++)
|
||||
new_arr[j] = arr[i];
|
||||
|
||||
return new_arr;
|
||||
return new_arr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,11 +147,11 @@ char **slice_array(char **arr, int beg, int end, bool asc)
|
||||
*/
|
||||
int get_null_term_arr_size(char **arr)
|
||||
{
|
||||
int k = 0;
|
||||
for (int i = 0; arr[i] != NULL; i++)
|
||||
k++;
|
||||
int k = 0;
|
||||
for (int i = 0; arr[i] != NULL; i++)
|
||||
k++;
|
||||
|
||||
return ++k;
|
||||
return ++k;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,19 +164,19 @@ int get_null_term_arr_size(char **arr)
|
||||
*/
|
||||
int append_to_str_arr(char ***arr, ssize_t *sz, char *str)
|
||||
{
|
||||
(*sz)++;
|
||||
(*sz)++;
|
||||
|
||||
char **tmp = realloc(*arr, sizeof(char *) * *sz);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Couldn't reallocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
*arr = tmp;
|
||||
char **tmp = realloc(*arr, sizeof(char *) * *sz);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Couldn't reallocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
*arr = tmp;
|
||||
|
||||
(*arr)[*sz - 1] = strdup(str);
|
||||
(*arr)[*sz - 1] = strdup(str);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,10 +186,10 @@ int append_to_str_arr(char ***arr, ssize_t *sz, char *str)
|
||||
*/
|
||||
char *get_curr_dir_name()
|
||||
{
|
||||
char *pwd = malloc(FILENAME_MAX);
|
||||
getcwd(pwd, FILENAME_MAX);
|
||||
char *pwd = malloc(FILENAME_MAX);
|
||||
getcwd(pwd, FILENAME_MAX);
|
||||
|
||||
return pwd;
|
||||
return pwd;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,60 +200,60 @@ char *get_curr_dir_name()
|
||||
*/
|
||||
int get_num_of_lines(FILE *file)
|
||||
{
|
||||
int n = 0;
|
||||
int ch, pch;
|
||||
long curr_pos = ftell(file);
|
||||
int n = 0;
|
||||
int ch, pch;
|
||||
long curr_pos = ftell(file);
|
||||
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
while ((ch = fgetc(file)) != EOF)
|
||||
{
|
||||
if (ch == '\n')
|
||||
n++;
|
||||
pch = ch;
|
||||
}
|
||||
while ((ch = fgetc(file)) != EOF)
|
||||
{
|
||||
if (ch == '\n')
|
||||
n++;
|
||||
pch = ch;
|
||||
}
|
||||
|
||||
if (pch != '\n')
|
||||
n++;
|
||||
if (pch != '\n')
|
||||
n++;
|
||||
|
||||
fseek(file, curr_pos, SEEK_SET);
|
||||
fseek(file, curr_pos, SEEK_SET);
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
bool str_is_in_arr(char **arr, size_t sz, char *str)
|
||||
{
|
||||
int first = 0;
|
||||
int last = sz - 1;
|
||||
int middle;
|
||||
int first = 0;
|
||||
int last = sz - 1;
|
||||
int middle;
|
||||
|
||||
while (first <= last)
|
||||
{
|
||||
middle = (first + last) / 2;
|
||||
int diff = strcmp(arr[middle], str);
|
||||
if (diff > 0)
|
||||
{
|
||||
first = middle + 1;
|
||||
}
|
||||
else if (diff == 0)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
last = middle - 1;
|
||||
}
|
||||
}
|
||||
while (first <= last)
|
||||
{
|
||||
middle = (first + last) / 2;
|
||||
int diff = strcmp(arr[middle], str);
|
||||
if (diff > 0)
|
||||
{
|
||||
first = middle + 1;
|
||||
}
|
||||
else if (diff == 0)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
last = middle - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *get_env_var(char *name)
|
||||
{
|
||||
char *env_var = getenv(name);
|
||||
if (env_var == NULL)
|
||||
{
|
||||
fprintf(stderr, "No $%s environment variable\n", name);
|
||||
return NULL;
|
||||
}
|
||||
char *env_var = getenv(name);
|
||||
if (env_var == NULL)
|
||||
{
|
||||
fprintf(stderr, "No $%s environment variable\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return strdup(env_var);
|
||||
return strdup(env_var);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user