Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

181 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minishell

A simplified shell implementation inspired by bash, developed as part of the 42 core curriculum.

Summary

Minishell is a challenging project that implements a basic shell similar to bash. It focuses on process creation and control, file descriptor manipulation, and signal handling. This project demonstrates our understanding of Unix system calls, environment variables, and shell functionality.

The implementation features a robust parser that handles commands with arguments, redirections, pipes, and heredocs. We've built a complete command execution system that supports both built-in commands and external binaries. Special attention was given to handling environment variables, signal interrupts, and maintaining proper exit status codes.

This project required deep knowledge of C programming, Unix processes, and shell behavior. The code is structured in a modular way, with clear separation between lexical analysis (tokenization), syntactic analysis (parsing), and execution.

Table of Contents

Quick overview

Minishell is a simple command-line interpreter that replicates core functionalities of bash. It provides command execution, environment variable management, pipes, redirections, and various shell builtins.

Features

  • Command execution from ($PATH) and absolute/relative paths
  • Environment variable expansion ($VAR)
  • Exit status expansion ($?)
  • Input/output redirections (>, <, >>)
  • Heredoc (<<)
  • Pipes (|)
  • Signal handling (Ctrl+C, Ctrl+D, Ctrl+\)
  • Builtin commands: echo, cd, pwd, export, unset, env, exit implemented by us

Building

Clone the repository and build the project:

git clone https://github.com/sknefi/Minishell.git
cd Minishell
make # build the project

Run the shell:

./minishell

For memory leak detection and detailed analysis, use the provided suppression file for readline:

valgrind --suppressions=readline.supp -s --leak-check=full ./minishell

This command will run Valgrind with readline-related leaks suppressed, showing a summary (-s) and performing full leak checking.

Architecture

Minishell is built with a modular architecture consisting of several key components:

Tokenization

The tokenization process in src/token/token.c breaks the input line into tokens. It handles:

  1. Command names and arguments
  2. Operators (|, >, <, >>, <<)
  3. Environment variables
  4. Quoted strings

Each token is assigned a type from the t_token_types enum and organized in a linked list for further processing.

Example:

echo"Hello $USER"| grep Hello > output.txt

Is tokenized as:

  • echo (TOKEN_WORD)
  • "Hello $USER" (TOKEN_WORD)
  • | (TOKEN_PIPE)
  • grep (TOKEN_WORD)
  • Hello (TOKEN_WORD)
  • > (TOKEN_REDIRECTION_OUT)
  • output.txt (TOKEN_WORD)

Parsing

The parser in src/ast/ast.c transforms the token list into an Abstract Syntax Tree (AST). It follows these steps:

  1. Recognize command structures
  2. Identify redirections and pipes
  3. Create a hierarchical tree representing command relationships
  4. Validate syntax

Abstract Syntax Tree

The AST uses node types from the t_node_types enum:

  • NODE_CMD: Command with arguments
  • NODE_PIPE: Pipe operator
  • NODE_REDIRECTION_IN, NODE_REDIRECTION_OUT, NODE_APPEND, NODE_HEREDOC: Redirection nodes

Each node contains:

  • Type
  • Data (command arguments or redirection filenames)
  • Left and right child nodes

Execution

The execution engine in src/exec/sh_exec.c traverses the AST and executes commands accordingly:

  1. For NODE_CMD, it first tries to execute as a builtin, then as an external command
  2. For NODE_PIPE, it creates a pipe and forks two processes
  3. For redirection nodes, it sets up file descriptors and executes the command

Usage Examples

Basic Commands

# Simple command execution
ls -la
# Environment variable usageecho$HOME# Path handling
/bin/ls
# Exit statusecho$?

Redirections

# Output redirection (create or overwrite)echo Hello > file.txt
# Output redirection (append)echo World >> file.txt
# Input redirection
cat < file.txt
# Multiple redirections
cat < input.txt > output.txt

Pipes

# Simple pipe
ls -la | grep .c
# Multiple pipes
ls -la | grep .c | wc -l
# Pipe with redirections
ls -la | grep .c > output.txt

Heredoc

# Basic heredoc
cat <<EOFThis is a heredocIt allows multiline inputEOF# Heredoc with pipes and redirections
cat <<EOF | grep hello > output.txthello worldgoodbye worldEOF

Builtins

echo

Displays a line of text.

echo Hello World
echo -n Hello World # No newlineecho -n -nn -nnnnnn Hello World # No newline

cd

Changes the current directory.

cd /absolute/path/to/directory
cd relative/path/to/directory
cd .. # Parent directorycd - # Previous directorycd# Home directorycd~# Home directory

pwd

Prints the current working directory.

pwd

export

Sets environment variables.

export VAR=value
export VAR1=value1 VAR2=value2 # export multiple variablesexport# Sorted list of all exported variables

unset

Removes environment variables.

unset VAR
unset VAR1 VAR2 # unset multiple variables

env

Displays all environment variables.

env

exit

Exits the shell with an optional status code.

exit

Exit Status

The exit status of the last command is stored in the $? variable, following bash conventions:

  • 0: Success
  • 1: General error
  • 127: Command not found
  • 130: Terminated by Ctrl+C (SIGINT)
  • 131: Terminated by Ctrl+\ (SIGQUIT)
  • Other values: Depends on the command and its exit status

Signal Handling

Minishell handles the following signals:

  • Ctrl+C (SIGINT): Interrupts the current command even in heredoc
  • Ctrl+D (EOF): Exits the shell (sends EOF to readline)
  • Ctrl+\ (SIGQUIT): Ignored in interactive mode, terminates with core dump in child processes

The signal handling is implemented in src/signal/signals_01.c and src/signal/signals_02.c.

Authors

This minishell project was built by:

  • Filip Karika
  • Tym Mateja

As part of the 42 School curriculum.

About

42 core - 3. Milestone

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages