Skip to content

claudio1code/minishell42_shellShock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

127 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This project has been created as part of the 42 curriculum by cacesar- and clados-s.

Minishell

Implementation of a mini shell in C, inspired by POSIX shell behavior, focusing on process control, pipeline execution, I/O redirections through file descriptors, and interactive command input using readline.

This project directly exercises core shell system calls (syscalls): process creation with fork(), program execution with execve(), synchronization with waitpid(), inter-process communication with pipe(), and input/output manipulation via open(), dup2(), and close(). It also includes signal handling (e.g., SIGINT) to keep the interactive experience stable.


Features

  • External command execution via PATH lookup and execve().
  • Pipelines with | (chained commands using pipe(), dup2(), and fork()).
  • Redirections: <, > (truncate), >> (append), and heredocs << (temporary .heredoc_N files).
  • Variable expansion: $VAR, plus $?, $$, and $# as implemented in the lexer.
  • Built-ins: echo, cd, pwd, export, unset, exit, env.
  • readline integration: editing, prompts, and command history (add_history).
  • Signal-aware interactive loop: handles SIGINT / SIGQUIT in the parent pipeline and restores default handlers in children where appropriate.

Project Architecture

This section describes the runtime flow as implemented in the project modules.

Lexer / Parsing (Input tokenization)

  • Interactive input: the line is read with readline() and stored in t_info->l (see srcs/utils/lexer_parser_utils.c).
  • Tokenization: the lexer (lexer() in srcs/lexer/lexer_init.c) walks the input string and splits it into a linked list of tokens (t_list), handling:
    • Separators and metacharacters: |, <, >, <<, >>, and \n.
    • Single and double quotes: reading mode is controlled by quotes(); inside double quotes, variable expansion is performed.
    • Variable expansion: handled by expansion() and var_maker() (e.g., $VAR, $?, $$, $#), querying the environment table (t_hashtable).
  • Execution structure: the parser (cmd() and helpers in srcs/parser/parser.c) converts the lexed list into a command list (t_token):
    • t_token->param: argument vector (command at index 0).
    • t_token->rdc: redirection vector in pairs (e.g., ">", "out.txt", "<", "in.txt", ...).
    • Pipelines are represented by chaining via t_token->next.

Execution (Processes with fork/execve/waitpid)

  • Input → execution: after lexer(), each “logical line” is executed through exec_pipeline() (see srcs/exec/exec_pipeline.c).
  • External command:
    • The shell creates a child process via fork() (exec_cmd() in srcs/exec/exec.c).
    • In the child, the executable path is resolved by get_cmd_path() (see srcs/exec/path_utils.c) using PATH.
    • Execution happens through execve(path, argv, envp), where envp is produced by ht_to_matrix() from the environment hashtable.
    • The parent synchronizes with waitpid() and converts the status into exit_code (including signal-related exit codes).

Pipes and Redirections (File descriptor management)

  • Pipeline: exec_pipeline() builds the execution chain with pipe() and fork() in a loop (loop_pipeline() in srcs/exec/exec_pipeline.c).
    • In each child:
      • If there is a previous pipe, prev_fd is connected to STDIN_FILENO via dup2().
      • If there is a next command, STDOUT_FILENO is connected to the write end of the pipe via dup2().
    • The parent closes unused descriptors and waits for all children via waitpid(-1, ...), preserving the status of the last command in the pipeline.
  • Redirections: applied by handle_redirections() (see srcs/exec/redirect.c), which:
    • Opens files via open() for input (<), output truncate/create (>), or output append (>>).
    • Redirects input/output via dup2(fd, STDIN_FILENO/STDOUT_FILENO) and closes the original fd.
  • Heredoc (<<):
    • Pre-processed by prepare_heredocs() (see srcs/exec/heredoc.c), which creates temporary files .heredoc_N and rewrites << into < pointing to the generated file.
    • Input is read with readline("> ") in a loop, stopping at the delimiter or EOF; SIGINT aborts the heredoc and propagates an appropriate exit code.

Built-ins (Implemented manually)

The shell implements built-ins without relying on external binaries (see srcs/builtins/ and srcs/builtins/builtins.c):

  • echo
  • cd
  • pwd
  • export
  • unset
  • exit
  • env

Important note: built-ins that must modify the parent process state (e.g., cd, export, unset, exit) are executed in the parent when there is no pipeline, detected by is_parent_builtin() (see srcs/exec/path_utils.c). In that case, the shell backs up and restores STDIN/STDOUT using dup()/dup2() while applying redirections.


Technical Challenges

A reliable minishell requires discipline in memory management and signal handling. The code must build dynamic structures (tokens, argument vectors, environment matrix, and PATH-resolved command paths) without leaking memory across iterations of the interactive loop. For that, the project centralizes cleanup routines (e.g., clean_shell() and clean_token()) and validates behavior with Valgrind (make leaks). At the same time, signal handling must balance interactivity (not “killing” the shell when pressing Ctrl-C) with child execution (restoring SIG_DFL in the child while keeping the parent consistent), producing correct exit codes for interruptions and signal-terminated programs.


Installation and Build

Prerequisites

  • OS: Linux is the primary target environment (POSIX syscalls used as in typical 42 clusters).
  • Toolchain: cc / gcc/clang-compatible compiler and make.
  • readline: development headers and library must be installed so linking with -lreadline succeeds (package names vary by distribution, e.g. libreadline-dev on Debian/Ubuntu).
  • valgrind (optional): required only if you intend to run make leaks for memory / FD auditing.

Clone and build

git clone https://github.com/claudio1code/minishell42_shellShock
cd minishell42_shellShock
make

Makefile targets

  • make / make all: builds the project and generates the minishell binary
  • make clean: removes object files (objs/)
  • make fclean: removes objects and the binary, cleans artifacts, and runs fclean in libft
  • make re: rebuilds from scratch
  • make leaks: runs the binary under Valgrind (includes suppressions for readline)

Usage Examples

After building, run:

./minishell

Simple commands

echo "Hello, world"
pwd
env

Variables and exit codes

export USER42=claudio
echo $USER42
false
echo $?
echo $$

Redirections

echo "line 1" > out.txt
echo "line 2" >> out.txt
cat < out.txt

Pipes

cat /etc/passwd | grep root | wc -l

Heredoc

cat << EOF
line A
line B
EOF

Directory Layout (Quick view)

  • includes/: main header (minishell.h) with types (t_info, t_token, t_hashtable) and prototypes.
  • srcs/lexer/: tokenization and reading rules (quotes/expansion).
  • srcs/parser/: builds the t_token execution list and performs syntax checks.
  • srcs/exec/: execution, pipeline, redirections, heredoc, PATH resolution.
  • srcs/builtins/: built-ins and environment utilities.
  • libft/: helper library (includes ft_printf, get_next_line, memory/string utilities).

Resources

  • POSIX.1—Shell Command Language—conceptual shell behavior and redirection semantics.
  • GNU Readline—library used for interactive input (readline(), history).
  • Manual pages commonly consulted during implementation: man 3 readline, man 2 fork, man 2 execve, man 2 waitpid, man 2 pipe, man 2 dup2, man 7 signal.

AI Usage

Portions of this README (structure, wording, and technical summaries) were drafted or refined with AI-assisted authoring tools (e.g., Cursor). The C implementation, design decisions in the codebase, and final review remain the responsibility of the project authors (cacesar-, clados-s). If you cite or reuse this repository in an academic setting, disclose tool assistance according to your institution’s policies.


License

This project is licensed under the MIT License. See the LICENSE file in the repository root for the full text.

About

This Project is about creating a simple shell, my own little bash

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors