The goal of the subject was to recreate some of the functionalities of bash (Version 3.2).
To see the exact requirements, check Chapter III and IV of the subject pdf.
If you find any problems with our minishell, here is the possibility to open an issue.
The existence of shells is linked to the very existence of IT. At the time, all coders agreed
that communicating with a computer using aligned 1/0 switches was seriously
irritating. It was only logical that they came up with the idea to communicate with
a computer using interactive lines of commands in a language somewhat close
to english.
With Minishell, you’ll be able to travel through time and come back to problems
people faced when Windows didn’t exist.
- this is a shell that can be compiled by running
make all
and then to run it./minishell
or instead you can runmake run
- now you are greeted with a prompt
minishell$
waiting for input just like any other shell - this project uses the readline libraries
readline/history.h
andreadline/readline.h
you can install those viabrew install readline
orapt-get install libreadline-dev
, thanks to those there is a working history of used commands - there is some memory-leaks caused by the readline-library
Just like most of the other shells we have divided our shell into 4 parts:
Those parts all have different tasks.
The lexer will get the input from the prompt once the user pressed enter
and create so called lexer_tokens
from it
The lexer_tokens are a 2D char array char *lexer_tokens[]
Now the given input i.e. cat <<eof >file1 && cat file1 && abc || wc <file1 | cat >file2
will result in lexer_tokens
like
lex_tok[0] | lex_tok[1] | lex_tok[2] | lex_tok[3] | lex_tok[4] | lex_tok[5] | lex_tok[6] | lex_tok[7] | lex_tok[8] | lex_tok[9] | lex_tok[10] | lex_tok[11] | lex_tok[12] | lex_tok[13] |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
cat |
<<eof |
>file1 |
&& |
cat |
file1 |
&& |
abc |
|| |
wc |
<file1 |
| |
cat |
>file2 |
back to contents
back to basic structure
The parser will then check for invalid syntax and create a kind of command table called parser_tokens
This is one element of the t_par_tok \*parser_tokens[]
:
typedef struct s_parser_tok
{
t_par_tok_type type;
t_redir_type redir_type[5];
char **cmd;
size_t cmd_size;
char **in;
size_t in_size;
char **out;
size_t out_size;
} t_par_tok;
So after the syntax-check the parser is able to get the command and its arguments as well as the redirections connected to the command.
back to contents
back to basic structure
The expander will take the parser tokens as argument.
The expander will interprete the environment variables into their corresponding value.
It also handles subshells, creates pipes and handles all the opening of input-/output-redirections and storing the correct ones in the executor tokens.
Subshells are executed by creating a child process which runs minishell without readline reading the input, but directly handing the correct, unparsed commands to it. And after the lexer is done, it will call the parser and so on.
After passing every of those parts without errors, it calls the executor in a loop and gives the executor the correct values to work with.
After a call of the executor, an error value, similar to errno, is set to the exit code of the executor.
This error value can be checked by running echo $?
and is used for the &&
and ||
logic.
This is the way the data is stored in the expander tokens and handed to the executor:
typedef struct s_expander_tokens
{
char **cmd;
int in;
int out;
bool is_pipe;
} t_exp_tok;
back to contents
back to basic structure
The executor does as it is called, it executes the command.
If the given command is an inbuilt, it will just run the command in the same process, if it isn't it will create a child process to run the command in.
After this is decided, the redirections of input and output are done and the command is executed.
The executor always returns the exit code of whatever it did.
back to contents
back to basic structure
If some form of wrong syntax gets detected, Invalid Syntax at token
is printed and the error value $?
is set to 258
If there was an invalid command used, command not found
is printed and the error value $?
is set to 127
back to contents