Skip to content

3lsy/minishell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minishell

Design

There are two main components on a shell:

  • Analyzer
  • Evaluator
---
title: Analyzer
---
flowchart LR
    input["INPUT: Raw CMD"]
    analyzer["ANALYZER"]
    output["OUTPUT: Command AST"]
    input --> analyzer
    analyzer --> output
Loading
---
title: Evaluator
---
flowchart LR
    input["INPUT: Command AST"]
    evaluator["EVALUATOR"]
    output["OUTPUT: CMD execution"]
    input --> evaluator
    evaluator --> output
Loading
---
title: Command Abstract Syntax Tree (AST)
---
%%{ init: { 'flowchart': { 'curve': 'stepAfter' } } }%%
graph TD
    A((Pipe)):::pipe --> B((Redir)):::redir
    A --> C((Pipe)):::pipe
    B --> D((Filename)):::arg
    B --> E((Redir)):::redir
    E --> EL((Filename)):::arg
    E --> ER((Redir)):::redir
    ER --> EER((Filename)):::arg
    ER --> EEL((CMD)):::cmd
    C --> F((Redir)):::redir
    F --> FL((Filename)):::arg
    F --> FR((Redir)):::redir
    FR --> FFR((Filename)):::arg
    FR --> FFL(... Redirs ...):::redir
    FFL --> FFFL((Redir)):::redir
    FFFL --> FFFR((Filename)):::arg
    FFFL --> FFFFL((CMD)):::cmd
    C --> G(... Pipes ...):::pipe
    G --> H((Pipe)):::pipe
    H --> HL((Redir)):::redir
    HL --> HR((Filename)):::arg
    H --> I((Redir)):::redir
    I --> IR((Filename)):::arg
    I --> IL(... Redirs ...):::redir
    IL --> IIL((CMD)):::cmd
    HL --> HHL(... Redirs ...):::redir
    HHL --> HHHL((CMD)):::cmd
    classDef pipe stroke:#f00
    classDef arg stroke:#0f0
    classDef cmd stroke:#ff0
    classDef redir stroke:#0ff
Loading
---
title: Simplified Abstract Syntax Tree (AST)
---
%%{ init: { 'flowchart': { 'curve': 'stepAfter' } } }%%
graph TD
    A((Pipe)):::pipe --> B((Redir\nFilename)):::redir
    A --> C((Pipe)):::pipe
    B --> E((Redir\nFilename)):::redir
    E --> ER((Redir\nFilename)):::redir
    ER --> EEL((CMD)):::cmd
    C --> F((Redir\nFilename)):::redir
    F --> FR((Redir\nFilename)):::redir
    FR --> FFL(... Redirs ...):::redir
    FFL --> FFFL((Redir\nFilename)):::redir
    FFFL --> FFFFL((CMD)):::cmd
    C --> G(... Pipes ...):::pipe
    G --> H((Pipe)):::pipe
    H --> HL((Redir\nFilename)):::redir
    H --> I((Redir\nFilename)):::redir
    I --> IL(... Redirs ...):::redir
    IL --> IIL((CMD)):::cmd
    HL --> HHL(... Redirs ...):::redir
    HHL --> HHHL((CMD)):::cmd
    classDef pipe stroke:#f00
    classDef arg stroke:#0f0
    classDef cmd stroke:#ff0
    classDef redir stroke:#0ff
Loading

We can reduce the AST into a linked list if we include the redirections' linked list as an attribute of a command

---
title: Reduced AST
---
%%{ init: { 'flowchart': { 'curve': 'stepAfter' } } }%%
graph LR
    a((CMD)):::cmd --> b((CMD)):::cmd --> c((...)):::cmd --> d((CMD)):::cmd
    classDef cmd stroke:#ff0
Loading
%%{ init: { 'flowchart': { 'curve': 'stepAfter' } } }%%
graph TB
    subgraph CMD node
    direction TB
    aa((CMD)):::cmd --> bb((Redir)):::redir -->bbb((Filename)):::arg
    cc-->cccc((...)):::arg
    bb-->cc((Redir)):::redir --> ccc((...)):::redir
    aa-->aaa((arg)):::arg-->arg2((arg)):::arg-->arg3((...)):::arg
    aa-->next((next)):::cmd-->next2((next)):::cmd-->next3((...)):::cmd

    
    classDef arg stroke:#0f0
    classDef cmd stroke:#ff0
    classDef redir stroke:#0ff
    end
Loading

Node structure

Command

typedef struct s_ast
{
	char		*bin;
	int		ac;
	char		**av;
	t_redir		*redir;
	struct s_ast	*next;
}	t_ast;

Redirections

typedef struct s_redir
{
	t_byte	id;
	char	*file;
}	t_redir;

Interface

In this minishell, the interface is very small and is mostly a tool for the Analyzer since it doesn't handle any pointer interaction. However it does handle:

  • A prompt to input a command
  • History
  • Handles user signals:
    Key Combination Signal Name
    ctrl-C SIGINT
    ctrl-D EOF (End of File)
    ctrl-\ SIGQUIT

Analyzer

The analyzer takes the command, analyze the lexic, syntax and semantic, and process the data into an Command AST, that the Evaluator will take and use it to evaluate the command, redirection, pipe, etc. It handles:

  • Lexic Analysis
  • Syntax Analysis
  • Semantic Analysis
  • Quotes
    Quotes Behavior
    Single quotes Prevent interpreting anything inside.
    Double quotes Prevent interpreting anything except $ inside.
    • Not interpret unclosed quotes
  • Translations
    • meta-characters
    • Relative path from command to absolute path
    • Env variables
    • $? which the evaluator has to save

Evaluator

The evaluator takes the Command AST, launch the appropriate executable on a child process, handling pipes, signal inheritance, clean process management, etc.

  • Search and launch executables
    • Based on the PATH env variable.
    • Based on an aboslute path
    • Based on builtins commands
  • Interpret redirections and pipes
    Redirection Symbol Description
    < Redirects input.
    > Redirects output.
    << Reads input until a line containing the delimiter is seen.
    >> Redirects output in append mode.
  • Builtins
    Command Option
    echo -n
    cd Only a relative or absolute path
    pwd No options
    export No options
    unset No options
    env No options or arguments
    exit No options

image

Entity Relationship Diagram

---
title: Shell Command Processing Flow
---
erDiagram
    Shell_Command }|--|{ Analyzer : "Analyze"
    Shell_Command }|--|{ Command_AST : "Creates"
    Analyzer }o--o{ Command_AST : "Creates"
    Command_AST }o--|| Evaluator : "Evaluate"
Loading

About

Unix shell from scratch in C

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •