MINISHELL PROJECT - HOW IT WORKS (STEP BY STEP)
========================================================
OVERVIEW:
---------
Minishell is a simplified version of bash that can execute commands, handle pipes,
redirections,
environment variables, and built-in commands. It provides a command-line interface
where users
can type commands and get results, just like a regular terminal.
MAIN COMPONENTS:
---------------
1. Input Reading and Parsing
2. Tokenization
3. Variable Expansion
4. Command Execution
5. Built-in Commands
6. Redirection and Pipes
7. Signal Handling
8. Environment Management
DETAILED STEP-BY-STEP WORKFLOW:
===============================
STEP 1: PROGRAM INITIALIZATION
------------------------------
- The program starts in main() function (srcs/main/minishell.c)
- Creates a mini structure that holds all the shell's state information
- Saves the original stdin and stdout file descriptors for later restoration
- Initializes environment variables from the system's environment
- Creates a "secret" environment copy for export command functionality
- Increments the SHLVL (shell level) environment variable
- Sets up the main execution loop
STEP 2: DISPLAY PROMPT AND READ INPUT
-------------------------------------
- The shell displays a colorful prompt: "😎 minishell ▸ " (or "▸ minishell ▸ " if
last command failed)
- Sets up signal handlers for Ctrl+C (SIGINT) and Ctrl+\ (SIGQUIT)
- Uses get_next_line() to read a complete line from the user
- If user presses Ctrl+D (EOF), the shell exits gracefully
STEP 3: INPUT PREPROCESSING
--------------------------
- Checks for unclosed quotes and shows syntax error if found
- Calls space_line() function which:
* Adds spaces around special characters (>, <, |, ;, >>)
* Marks dollar signs ($) for variable expansion by converting them to negative
values
* This makes tokenization easier by ensuring separators are isolated
STEP 4: TOKENIZATION
-------------------
- The preprocessed line goes to get_tokens() function
- Creates a linked list of tokens, where each token contains:
* The string content
* A type (CMD, ARG, PIPE, TRUNC, APPEND, INPUT, END, EMPTY)
* Pointers to previous and next tokens
- Handles quoted strings (both single and double quotes)
- Handles escaped characters with backslashes
- Determines token types based on content and position
STEP 5: TOKEN TYPE REFINEMENT
-----------------------------
- After initial tokenization, the type_arg() function refines token types:
* First token after separator or start = CMD (command)
* Subsequent tokens = ARG (arguments)
* Special characters get their specific types (PIPE, TRUNC, etc.)
- The squish_args() function reorganizes arguments to be next to their commands
STEP 6: SYNTAX VALIDATION
------------------------
- check_line() function validates the token sequence
- Ensures pipes don't start or end the command
- Checks that redirections have proper file arguments
- Returns error for invalid syntax patterns
STEP 7: COMMAND EXECUTION PREPARATION
------------------------------------
- The minishell() function starts the execution process
- Finds the first command token
- Enters a loop to process all commands in the input line
- Sets up execution state variables (charge, parent, last)
STEP 8: REDIRECTION AND EXECUTION HANDLER
-----------------------------------------
- redir_and_exec() function handles each command and its redirections:
* Checks for output redirection (>, >>)
* Checks for input redirection (<)
* Handles pipes (|) by creating child processes
* Recursively processes the next command in the pipeline
* Finally executes the actual command
STEP 9: VARIABLE EXPANSION
-------------------------
- Before execution, the expansions() function processes each argument:
* Replaces $VARIABLE with the actual environment variable value
* Handles $? (exit status of last command)
* Handles $0, $1, etc. (though limited in this implementation)
* Leaves single-quoted strings unchanged
* Processes double-quoted strings with expansions
STEP 10: COMMAND EXECUTION DECISION
----------------------------------
- exec_cmd() function determines how to execute the command:
* Special case: "exit" command is handled immediately
* Checks if command is a built-in using is_builtin()
* If built-in: calls exec_builtin()
* If external: calls exec_bin()
STEP 11A: BUILT-IN COMMAND EXECUTION
------------------------------------
- Built-in commands are executed directly within the shell process:
* echo: prints arguments (with -n flag support)
* cd: changes directory and updates PWD environment variable
* pwd: prints current working directory
* env: displays all environment variables
* export: adds/modifies environment variables
* unset: removes environment variables
* exit: terminates the shell
STEP 11B: EXTERNAL COMMAND EXECUTION
------------------------------------
- For external commands, exec_bin() function:
* Searches for the executable in PATH directories
* If command contains '/', treats it as absolute/relative path
* Creates a child process using fork()
* In child process: converts environment to array and calls execve()
* In parent process: waits for child to complete
* Returns the exit status
STEP 12: REDIRECTION HANDLING
----------------------------
- Output redirection (>): Opens file for writing, truncates if exists
- Append redirection (>>): Opens file for writing, appends to end
- Input redirection (<): Opens file for reading
- Uses dup2() to redirect file descriptors to stdin/stdout
- Handles file access errors gracefully
STEP 13: PIPE HANDLING
---------------------
- minipipe() function creates a pipe between two commands:
* Creates pipe file descriptors using pipe()
* Forks the process
* In child: connects pipe input to stdin, continues with next command
* In parent: connects pipe output to stdout, executes current command
* This creates a chain where output of one command feeds into the next
STEP 14: SIGNAL HANDLING
-----------------------
- Ctrl+C (SIGINT): Interrupts current command, returns to prompt
- Ctrl+\ (SIGQUIT): Quits current command with core dump message
- Different behavior when signal occurs during command vs. at prompt
- Updates global signal structure to track signal state
STEP 15: CLEANUP AND CONTINUATION
--------------------------------
- After command execution completes:
* Restores original stdin/stdout file descriptors
* Closes any open pipe file descriptors
* Resets file descriptor state
* Waits for any remaining child processes
* Updates the return status for $? variable
* Frees the token list memory
STEP 16: LOOP CONTINUATION
-------------------------
- If exit flag is not set, returns to step 2 for next command
- The shell continues running until user types "exit" or presses Ctrl+D
- On exit, frees all allocated memory and returns the last exit status
ERROR HANDLING:
--------------
- Memory allocation failures
- File access errors for redirections
- Command not found errors
- Permission denied errors
- Syntax errors in input
- Signal interruptions
SPECIAL FEATURES:
----------------
- Maintains command history through session
- Supports complex command chaining with pipes and redirections
- Handles nested quotes and escaped characters
- Manages environment variables properly
- Provides colored prompt with status indication
- Maintains shell level tracking (SHLVL)
This implementation provides a fully functional shell experience while maintaining
simplicity and clarity in the codebase structure.