___ ___ _ _ _ _ _{ } / __| __| /_\ __| |_ ___| | | _( | ) \__ \ _| / _ \ (_-< ' \/ -_) | | _{__(} _} |___/___/_/ \_\/__/_||_\___|_|_| ( / ) { __()__ _ _} -42 school project minishell- {(_( ) _ () ( {}_ _/ --\_ ( | ( - - - \ (__|_ _|- -- -_) \\ ( --_) | (|_) L_ (|) by: Fauna Polaris \_|) || Nicolas Prudencio
The SEAshell is a simple, educational implementation of a bash-like shell environment created as a part of the 42 school curriculum; it was created as a learning project and is very limited in its utility.
If you put the SEAshell really close to your ears you can hear the sound of a mechanical keyboard.
- access and control of environment variables;
- builtin commands;
- input/output redition and file managment;
- execution of any command accesible through PATH.
There is no dependency to build and run the SEAshell; you can simply clone it and compile it using make.
After compilation, a program named minishell will be created which you can run directly from the terminal:
./minishell
While running, the program will display a prompt that can be used just like another inplementation of a shell environment such as bash or zsh.
The SEAshell is composed by three main components: Lexer, Parser and executor; they will be called in order, creating a simple flow:
- The user inputs a string using the open prompt;
- The lexer is called, using the input string to create a structure of tokens;
- The parser is called, using the tokens to check for syntax errors and create a command table;
- The executor is called, reading from the command table and executing each command.
In parallel to this main flow, the program will be handling the following signals:
- SIGINT;
- SIGQUIT;
- SIGPIPE.
Acts as a tokenizer, separating the input string into tokens; Tokens are stored as a linked list;
Input:
echo -n Fauna Polaris
output: {Literal Value of string, simplified symbolic representation}
{echo, <TERMINAL>}, {-n, <FLAG>}, {Fauna, <STRING>}, {Polaris, <STRING>}
In this example, the lexer shows its utility by separating the two very different strings: "Fauna" and "Polaris", as a common entity denoted as the token <STRING>, while maintaining the literal value of the string intact; this process will make the job of the parser way easier.
Breaks down the list of tokens into a comand table ready to be executed; the parsing algorithm in a simple implementation of a LL(1) algorithm using a pushdown automaton as a tool.
The automaton is a mathematical concept defined as a 7-tuple formed by:
M = ( Q, Σ, Γ, δ,
- Q is a finite set of states;
- Σ is a finite set which is called the input alphabet;
-
$Γ$ is a finite set which is called the stack alphabet; - δ is a finite subset of Q X (Σ ⋃ {ε}) X Γ X Q X
$Γ^*$ , the transition relation; -
$q_{0}$ ∈ Q is the start state; - Z ∈ Γ is the initial stack symbol;
- F ⊆ Q is the set of accepting states;
For a more indepth breakdown of the functionality of pushdown automaton in general use this link.
For explanation of the specific automaton developed for this project go to the documentation of the parser.
Utilizing the complex structure of the automaton, the return comand table is also a linked list, holding different commands; each command in the list is formed by two elements, a char ** representing the command itself and its arguments to be sent for execution and a int [2] which represents two file descriptors.
Execute each command in a new process, managing the input and output of each process based on the information from the comand table;