Skip to content

ravazque/minishell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

125 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MINISHELL

πŸ“– About

"minishell" is a project at 42 Madrid that involves creating a simple shell that replicates basic functionalities of bash. This project introduces command parsing, process management, signal handling, and teaches how to implement a command-line interpreter in a systematic way.

The goal is to implement a shell program that can execute commands, manage environment variables, handle redirections and pipes, and provide a user-friendly interactive experience similar to bash.

🎯 Objectives

  • Understanding and implementing command-line parsing and tokenization
  • Learning about process creation and management with fork() and execve()
  • Managing pipes and redirections for inter-process communication
  • Implementing built-in shell commands
  • Handling signals (SIGINT, SIGQUIT, EOF)
  • Managing environment variables and shell variables
  • Implementing command history functionality
  • Handling quotes and special characters properly

πŸ“‹ Function Overview

minishell

Concepts

Description: A minimal shell implementation that mimics bash behavior Usage: ./minishell or ./minishell -c "command" Behavior: Reads and executes commands interactively or from arguments

int main(int argc, char **argv, char **envp);

Use of processes and signal handling

The implementation of minishell requires creating processes and handling signals. For this, several system calls are used:

The main system calls and functions are:

  • fork() ➜ Creates a child process to execute commands.
pid_t pid = fork();
  • execve() ➜ Replaces the current process with a new program.
execve(cmd_path, cmd_args, envp);
  • pipe() ➜ Creates a pipe for communication between processes.
int pipefd[2];
pipe(pipefd);
  • dup2() ➜ Duplicates file descriptors for redirection.
dup2(fd, STDIN_FILENO);
  • signal() / sigaction() ➜ Sets up signal handlers for Ctrl-C, Ctrl-, etc.
signal(SIGINT, signal_handler);
  • readline() ➜ Reads a line from the terminal with line editing capabilities.
char *line = readline("minishell> ");
  • add_history() ➜ Adds a command to the history list.
add_history(line);

These functions are essential for implementing minishell, as they allow command execution, process management, and user interaction.

Features and Behavior

Interactive Mode

  • Prompt: Displays custom prompt with user@hostname:path (git_branch) $
  • Command execution: Supports absolute paths, relative paths, and PATH resolution
  • History: Full command history navigation with up/down arrows
  • Signals: Proper handling of:
  • Ctrl-C: Interrupts current command (SIGINT)
  • Ctrl-D: Exits shell when line is empty (EOF)
  • Ctrl-\: Does nothing in interactive mode (SIGQUIT)

Supported Features

Environment Variables:

  • $VAR - Environment variable expansion
  • $? - Exit status of last command
  • $0 - Shell name
  • $$ - Shell process ID
  • $_ - Last argument of previous command

Redirections:

  • < - Input redirection
  • > - Output redirection (truncate)
  • >> - Output redirection (append)
  • << - Heredoc (read until delimiter)

Pipes:

  • | - Connect output of one command to input of another

Quotes:

  • 'single quotes' - Preserve literal value of all characters
  • "double quotes" - Preserve literal value except $ and \

Built-in Commands

  • echo [-n] - Print arguments to stdout
  • cd [path] - Change working directory
  • pwd - Print working directory
  • export [var=value] - Set environment variables
  • unset [var] - Unset environment variables
  • env - Display environment variables
  • exit [n] - Exit shell with status code

Command Mode

./minishell -c "command"
# Executes command and exits

πŸš€ Installation & Structure

πŸ“₯ Download & Compilation
# Clone the repository
git clone https://github.com/ravazque/minishell.git
cd minishell

# Compile the program
make

# Clean object files
make clean

# Clean everything including executable
make fclean

# Recompile everything
make re

# Run the program
./minishell

πŸ“ Project Structure
minishell/
β”œβ”€β”€β”¬ include/
β”‚  β”œβ”€β”€ colors.h                         # Color definitions for terminal output
β”‚  └── minishell.h                      # Main header with prototypes and structures
β”œβ”€β”€β”¬ src/
β”‚  β”œβ”€β”€ minishell.c                      # Main entry point
β”‚  β”œβ”€β”€β”¬ aux_libft/                      # Custom library functions
β”‚  β”‚  β”œβ”€β”€ include/                      # Library headers
β”‚  β”‚  └── src/                          # Library implementations
β”‚  β”œβ”€β”€β”¬ aux_minishell/                  # Auxiliary minishell functions
β”‚  β”‚  β”œβ”€β”€ error.c                       # Error handling
β”‚  β”‚  β”œβ”€β”€ init.c                        # Initialization routines
β”‚  β”‚  β”œβ”€β”€ loop.c                        # Main shell loop
β”‚  β”‚  β”œβ”€β”€ mshlvl.c                      # Shell level management
β”‚  β”‚  └── underscore.c                  # $_ variable handling
β”‚  β”œβ”€β”€β”¬ built_ins/                      # Built-in commands
β”‚  β”‚  β”œβ”€β”€ builtin_echo.c                # echo command
β”‚  β”‚  β”œβ”€β”€ builtin_exit.c                # exit command
β”‚  β”‚  β”œβ”€β”€ builtin_pwd.c                 # pwd command
β”‚  β”‚  β”œβ”€β”€ builtin_unset.c               # unset command
β”‚  β”‚  β”œβ”€β”€ builtins_core.c               # Core built-in dispatcher
β”‚  β”‚  β”œβ”€β”€ builtins_utils.c              # Built-in utilities
β”‚  β”‚  β”œβ”€β”€β”¬ builtin_cd/                  # cd command implementation
β”‚  β”‚  β”‚  β”œβ”€β”€ builtin_cd.c               # Main cd logic
β”‚  β”‚  β”‚  β”œβ”€β”€ builtin_cd_path.c          # Path resolution
β”‚  β”‚  β”‚  └── builtin_cd_utils.c         # cd utilities
β”‚  β”‚  β”œβ”€β”€β”¬ builtin_env/                 # env command implementation
β”‚  β”‚  β”‚  β”œβ”€β”€ builtin_env.c              # Main env logic
β”‚  β”‚  β”‚  β”œβ”€β”€ builtin_env_cmd.c          # env command parsing
β”‚  β”‚  β”‚  β”œβ”€β”€ builtin_env_exec.c         # env execution
β”‚  β”‚  β”‚  β”œβ”€β”€ builtin_env_fork.c         # env fork handling
β”‚  β”‚  β”‚  └── builtins_setenv.c          # Environment variable setter
β”‚  β”‚  └──┬ builtin_export/              # export command implementation
β”‚  β”‚     β”œβ”€β”€ builtin_export.c           # Main export logic
β”‚  β”‚     β”œβ”€β”€ builtin_export_print.c     # Print exported variables
β”‚  β”‚     β”œβ”€β”€ builtin_export_set.c       # Set exported variables
β”‚  β”‚     β”œβ”€β”€ builtin_export_utils.c     # Export utilities
β”‚  β”‚     └── builtin_export_validate.c  # Export validation
β”‚  β”œβ”€β”€β”¬ cleaner/                        # Memory cleanup functions
β”‚  β”‚  β”œβ”€β”€ cleanup_exec.c                # Execution cleanup
β”‚  β”‚  β”œβ”€β”€ cleanup.c                     # General cleanup
β”‚  β”‚  └── free_structs.c                # Structure deallocation
β”‚  β”œβ”€β”€β”¬ execution/                      # Command execution
β”‚  β”‚  β”œβ”€β”€β”¬ executor/                    # Main executor
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_empty.c               # Funcions for empty commands
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_child.c               # Child process execution
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_env.c                 # Environment for execution
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_path.c                # Path resolution
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_pipes.c               # Pipe management
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_single.c              # Single command execution
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_utils.c               # Execution utilities
β”‚  β”‚  β”‚  β”œβ”€β”€ exec_wait.c                # Process wait handling
β”‚  β”‚  β”‚  └── executor.c                 # Main executor logic
β”‚  β”‚  β”œβ”€β”€β”¬ heredocs/                    # Heredoc implementation
β”‚  β”‚  β”‚  β”œβ”€β”€ heredocs_collect.c         # Line collection
β”‚  β”‚  β”‚  β”œβ”€β”€ heredocs.c                 # Main heredoc logic
β”‚  β”‚  β”‚  └── heredocs_handler.c         # Heredoc handlers
β”‚  β”‚  └──┬ redirs/                      # Redirection handling
β”‚  β”‚     └── redirections.c             # Redirection setup
β”‚  β”œβ”€β”€β”¬ fork_bomb/                      # Fork bomb detection
β”‚  β”‚  β”œβ”€β”€ fork_bomb.c                   # Fork bomb handler
β”‚  β”‚  └── fork_bomb_utils.c             # Detection utilities
β”‚  β”œβ”€β”€β”¬ parse/                          # Input parsing
β”‚  β”‚  β”œβ”€β”€ parse.c                       # Main parser
β”‚  β”‚  β”œβ”€β”€ parse_assign.c                # Assignment parsing
β”‚  β”‚  β”œβ”€β”€ parse_utils.c                 # Parser utilities
β”‚  β”‚  β”œβ”€β”€β”¬ expand/                      # Variable expansion
β”‚  β”‚  β”‚  β”œβ”€β”€ expand.c                   # Main expander
β”‚  β”‚  β”‚  β”œβ”€β”€ expand_extract.c           # Variable extraction
β”‚  β”‚  β”‚  β”œβ”€β”€ expand_redirs.c            # Redirection expansion
β”‚  β”‚  β”‚  β”œβ”€β”€ expand_str.c               # String expansion
β”‚  β”‚  β”‚  β”œβ”€β”€ expand_tilde.c             # Tilde expansion
β”‚  β”‚  β”‚  β”œβ”€β”€ expand_utils.c             # Expansion utilities
β”‚  β”‚  β”‚  β”œβ”€β”€ expand_vars.c              # Variable expansion
β”‚  β”‚  β”‚  └──┬ expand_split/             # Word splitting
β”‚  β”‚  β”‚     β”œβ”€β”€ expand_split.c          # Main word splitter
β”‚  β”‚  β”‚     β”œβ”€β”€ expand_split_add.c      # Add split tokens
β”‚  β”‚  β”‚     β”œβ”€β”€ expand_split_count.c    # Count split words
β”‚  β”‚  β”‚     β”œβ”€β”€ expand_split_helpers.c  # Split helpers
β”‚  β”‚  β”‚     β”œβ”€β”€ expand_split_utils.c    # Split utilities
β”‚  β”‚  β”‚     └── expand_split_word.c     # Word extraction
β”‚  β”‚  β”œβ”€β”€β”¬ lexer/                       # Lexical analysis
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer.c                    # Main lexer
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_classify.c           # Token classification
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_cmd_create.c         # Command creation
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_pipe_split.c         # Pipe splitting
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_pipe_valid.c         # Pipe validation
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_quotes.c             # Quote handling
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_redir.c              # Redirection tokens
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_redir_proc.c         # Redirection processing
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_token.c              # Token creation
β”‚  β”‚  β”‚  β”œβ”€β”€ lexer_token_arr.c          # Token array conversion
β”‚  β”‚  β”‚  └── lexer_utils.c              # Lexer utilities
β”‚  β”‚  └──┬ tokenizer/                   # Tokenization
β”‚  β”‚     β”œβ”€β”€ tokenizer.c                # Main tokenizer
β”‚  β”‚     β”œβ”€β”€ tokenizer_handlers.c       # Character handlers
β”‚  β”‚     β”œβ”€β”€ tokenizer_helpers.c        # Helper functions
β”‚  β”‚     β”œβ”€β”€ tokenizer_parts.c          # Token parts handling
β”‚  β”‚     └── tokenizer_utils.c          # Tokenizer utilities
β”‚  β”œβ”€β”€β”¬ prompt/                         # Prompt generation
β”‚  β”‚  β”œβ”€β”€ prompt.c                      # Main prompt builder
β”‚  β”‚  β”œβ”€β”€ prompt_git.c                  # Git branch detection
β”‚  β”‚  β”œβ”€β”€ prompt_path.c                 # Path formatting
β”‚  β”‚  └── prompt_utils.c                # Prompt utilities
β”‚  └──┬ signals/                        # Signal handling
β”‚     β”œβ”€β”€ signals.c                     # Main signal setup
β”‚     └── signal_handlers.c             # Signal handlers
β”œβ”€β”€ Makefile                            # Compilation rules
└── README.md                           # Project documentation

πŸ’‘ Key Learning Outcomes

The minishell project teaches advanced system programming and shell implementation concepts:

  • Process Management: Understanding fork(), execve(), and wait() system calls
  • Command Parsing: Learning to tokenize and parse complex command-line syntax
  • Signal Handling: Proper management of SIGINT, SIGQUIT, and EOF signals
  • File Descriptor Management: Deep knowledge of redirections and pipes
  • Environment Management: Manipulating and maintaining environment variables
  • Error Handling: Robust error checking and proper exit codes
  • Memory Management: Preventing leaks in a complex interactive program

βš™οΈ Technical Specifications

  • Language: C (C90 standard)
  • Compiler: cc with flags -Wall -Wextra -Werror
  • System Calls: fork(), execve(), pipe(), dup2(), waitpid(), signal()
  • External Functions: readline(), add_history() (GNU Readline library)
  • Platform: UNIX-like systems (Linux, macOS)
  • Memory Management: Proper cleanup of all allocated memory and file descriptors
  • Process Handling: Parent-child process synchronization and signal propagation
  • Exit Codes: Proper exit status propagation and $? handling

Note

This project serves as a comprehensive introduction to shell programming and demonstrates proficiency in process management parsing, and inter-process communication concepts.

About

A simplified bash shell implemented in C. Supports pipes, redirections, environment variables, heredoc and built-ins.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors