Added exec builtin command
This commit is contained in:
parent
922424abd4
commit
d125a84156
@ -7,12 +7,13 @@ Work is still in porgress, buf when you will see a "finished" topic assigned to
|
|||||||
# Supported features
|
# Supported features
|
||||||
* Command input with `left` and `right` arrow, `home` and `end` keys navigation and `backspace`, `delete` support
|
* Command input with `left` and `right` arrow, `home` and `end` keys navigation and `backspace`, `delete` support
|
||||||
* Running commands in separate process and termination them with `ctrl+c`
|
* Running commands in separate process and termination them with `ctrl+c`
|
||||||
* `cd` and `exit` builtin commands
|
* `cd`, `exit` and `exec` builtin commands
|
||||||
* Files and commands from `/usr/bin` autocompletion on `Tab` keypress
|
* Files and commands from `/usr/bin` autocompletion on `Tab` keypress
|
||||||
|
|
||||||
# Builtin commands
|
# Builtin commands
|
||||||
* `cd`: changes current working directory to the one specified by user. If no arguments provided, shows error.
|
* `cd`: changes current working directory to the one specified by user. If no arguments provided, shows error.
|
||||||
* `exit`: exits shell
|
* `exit`: exits shell
|
||||||
|
* `exec`: executes entered command and exits
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
* Pipes and files input/output
|
* Pipes and files input/output
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <termio.h>
|
#include <termio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
enum keys {
|
enum keys {
|
||||||
DELETE_KEY = 1000,
|
DELETE_KEY = 1000,
|
||||||
@ -18,7 +19,7 @@ enum keys {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void change_mode(int on);
|
void change_mode(int on);
|
||||||
char *read_line(char **line);
|
char *read_line();
|
||||||
int process_keypress(char c);
|
int process_keypress(char c);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -15,7 +15,6 @@
|
|||||||
#define BUFF_SIZE 1024
|
#define BUFF_SIZE 1024
|
||||||
#define ARG_SIZE 32
|
#define ARG_SIZE 32
|
||||||
|
|
||||||
char *read_line();
|
|
||||||
int process_line(char *line, char ***args);
|
int process_line(char *line, char ***args);
|
||||||
int launch(char **args);
|
int launch(char **args);
|
||||||
void process_command();
|
void process_command();
|
||||||
@ -25,6 +24,7 @@ void sig_handler();
|
|||||||
|
|
||||||
int sh_cd(char **args);
|
int sh_cd(char **args);
|
||||||
int sh_exit(char **args);
|
int sh_exit(char **args);
|
||||||
|
int sh_exec(char **args);
|
||||||
|
|
||||||
char *compose_prompt();
|
char *compose_prompt();
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
extern FILE *log_file;
|
extern FILE *log_file;
|
||||||
|
|
||||||
@ -21,5 +22,7 @@ void remove_on_pos(char **str, int pos);
|
|||||||
int sep_string(char *line, char ***toks, char *sep);
|
int sep_string(char *line, char ***toks, char *sep);
|
||||||
char *trim_string(char **str);
|
char *trim_string(char **str);
|
||||||
void free_str_arr(char **arr);
|
void free_str_arr(char **arr);
|
||||||
|
char **slice_array(char **arr, int beg, int end, bool asc);
|
||||||
|
int get_null_term_arr_size(char **arr);
|
||||||
|
|
||||||
#endif
|
#endif
|
15
src/input.c
15
src/input.c
@ -27,11 +27,13 @@ void change_mode(int on)
|
|||||||
* @param line
|
* @param line
|
||||||
* @return char*
|
* @return char*
|
||||||
*/
|
*/
|
||||||
char *read_line(char **line)
|
char *read_line()
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int n = 0, pos = 0;
|
int n = 0, pos = 0;
|
||||||
|
|
||||||
|
char *line = strdup("");
|
||||||
|
|
||||||
while (read(STDIN_FILENO, &c, 1))
|
while (read(STDIN_FILENO, &c, 1))
|
||||||
{
|
{
|
||||||
c = process_keypress(c);
|
c = process_keypress(c);
|
||||||
@ -41,7 +43,7 @@ char *read_line(char **line)
|
|||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case DELETE_KEY:
|
case DELETE_KEY:
|
||||||
delete_key(pos, &n, line);
|
delete_key(pos, &n, &line);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LEFT_KEY:
|
case LEFT_KEY:
|
||||||
@ -61,19 +63,18 @@ char *read_line(char **line)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BACKSPACE_KEY:
|
case BACKSPACE_KEY:
|
||||||
backspace_key(&pos, &n, line);
|
backspace_key(&pos, &n, &line);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENTER_KEY:
|
case ENTER_KEY:
|
||||||
new_line();
|
new_line();
|
||||||
|
|
||||||
return *line;
|
return line;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAB_KEY:
|
case TAB_KEY:
|
||||||
{
|
{
|
||||||
// TODO: autocomplete
|
tab_key(&pos, &n, &line);
|
||||||
tab_key(&pos, &n, line);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ char *read_line(char **line)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if ((c > 31 && c < 127) || (c > 127 && c < 255))
|
if ((c > 31 && c < 127) || (c > 127 && c < 255))
|
||||||
printable_key(&pos, &n, (char)c, line);
|
printable_key(&pos, &n, (char)c, &line);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ void tab_key(int *pos, int *n, char **line)
|
|||||||
*pos = strlen(*line);
|
*pos = strlen(*line);
|
||||||
*n = *pos;
|
*n = *pos;
|
||||||
|
|
||||||
char *buff = strdup(""), *output = NULL;
|
char *buff = strdup("");
|
||||||
size_t buff_size = 1;
|
size_t buff_size = 1;
|
||||||
|
|
||||||
char **complete_options = malloc(0), *to_complete = NULL;
|
char **complete_options = malloc(0), *to_complete = NULL;
|
||||||
@ -167,7 +167,7 @@ void tab_key(int *pos, int *n, char **line)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
append_to_buff(&buff, &buff_size, "\x1b[2K\r", 5);
|
append_to_buff(&buff, &buff_size, "\n", 1);
|
||||||
|
|
||||||
if ((int)opts_sz < 1)
|
if ((int)opts_sz < 1)
|
||||||
{
|
{
|
||||||
@ -193,7 +193,6 @@ void tab_key(int *pos, int *n, char **line)
|
|||||||
|
|
||||||
free(buff);
|
free(buff);
|
||||||
free(to_complete);
|
free(to_complete);
|
||||||
free_str_arr(complete_options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
48
src/shell.c
48
src/shell.c
@ -6,11 +6,13 @@
|
|||||||
/* Global definitions */
|
/* Global definitions */
|
||||||
char *builtin[] = {
|
char *builtin[] = {
|
||||||
"cd",
|
"cd",
|
||||||
"exit"};
|
"exit",
|
||||||
|
"exec"};
|
||||||
|
|
||||||
int (*builtin_func[])(char **) = {
|
int (*builtin_func[])(char **) = {
|
||||||
&sh_cd,
|
&sh_cd,
|
||||||
&sh_exit};
|
&sh_exit,
|
||||||
|
&sh_exec};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Function for main loop. It prints prompt, reads user's input and executes it
|
* @brief Function for main loop. It prints prompt, reads user's input and executes it
|
||||||
@ -18,25 +20,17 @@ int (*builtin_func[])(char **) = {
|
|||||||
void process_command()
|
void process_command()
|
||||||
{
|
{
|
||||||
char **args = NULL;
|
char **args = NULL;
|
||||||
int status;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
char *line = strdup("");
|
|
||||||
|
|
||||||
char *prompt = compose_prompt();
|
char *prompt = compose_prompt();
|
||||||
|
|
||||||
print_str(prompt, strlen(prompt));
|
print_str(prompt, strlen(prompt));
|
||||||
|
|
||||||
line = read_line(&line);
|
char *line = read_line();
|
||||||
|
|
||||||
process_line(line, &args);
|
process_line(line, &args);
|
||||||
status = execute(args);
|
int status = execute(args);
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
free(prompt);
|
free(prompt);
|
||||||
free_str_arr(args);
|
free_str_arr(args);
|
||||||
} while (status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,15 +101,7 @@ int launch(char **args)
|
|||||||
|
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
{
|
{
|
||||||
change_mode(0);
|
sh_exec(args);
|
||||||
signal(SIGINT, SIG_DFL);
|
|
||||||
|
|
||||||
if (execvp(args[0], args) < 0)
|
|
||||||
{
|
|
||||||
perror("myshell");
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
else if (pid < 0)
|
else if (pid < 0)
|
||||||
{
|
{
|
||||||
@ -140,11 +126,11 @@ int launch(char **args)
|
|||||||
int sh_cd(char **args)
|
int sh_cd(char **args)
|
||||||
{
|
{
|
||||||
if (args[1] == NULL)
|
if (args[1] == NULL)
|
||||||
fprintf(stderr, "myshell: expected arguments for \"cd\"\n");
|
chdir(getenv("HOME"));
|
||||||
else if (chdir(args[1]) < 0)
|
else if (chdir(args[1]) < 0)
|
||||||
perror("myshell");
|
perror("myshell");
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,6 +144,22 @@ int sh_exit(char **args)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sh_exec(char **args)
|
||||||
|
{
|
||||||
|
change_mode(0);
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
|
||||||
|
if (strcmp(args[0], "exec") == 0)
|
||||||
|
args = slice_array(args, 1, -1, 1);
|
||||||
|
|
||||||
|
if (execvp(args[0], args) < 0)
|
||||||
|
{
|
||||||
|
perror("myshell");
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
char *compose_prompt()
|
char *compose_prompt()
|
||||||
{
|
{
|
||||||
char *prompt = strdup("\n");
|
char *prompt = strdup("\n");
|
||||||
|
@ -77,6 +77,8 @@ size_t list_strings_containing(struct tree_node *root, char *key, char ***string
|
|||||||
{
|
{
|
||||||
size_t amount = 0;
|
size_t amount = 0;
|
||||||
|
|
||||||
|
free(*strings);
|
||||||
|
|
||||||
*strings = malloc(amount * sizeof(char *));
|
*strings = malloc(amount * sizeof(char *));
|
||||||
|
|
||||||
struct tree_node *current = root;
|
struct tree_node *current = root;
|
||||||
|
28
src/utils.c
28
src/utils.c
@ -89,3 +89,31 @@ void free_str_arr(char **arr)
|
|||||||
free(arr[i]);
|
free(arr[i]);
|
||||||
free(arr);
|
free(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
char **new_arr = malloc(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];
|
||||||
|
|
||||||
|
return new_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_null_term_arr_size(char **arr)
|
||||||
|
{
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 0; arr[i]!= NULL; i++)
|
||||||
|
k++;
|
||||||
|
|
||||||
|
return k;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user