No description
  • C 94.2%
  • Makefile 5.8%
Find a file
Pierre Jarnac 2c2ea812ea
Some checks failed
Makefile Action / build (push) Has been cancelled
feat: add README.md
2026-07-01 17:01:54 +02:00
.github/workflows Update makefile.yml 2025-03-06 11:29:02 +01:00
includes signals fix 2025-04-14 10:43:51 +02:00
lib/libft fix: des leaks si fail sur cpy env 2025-04-22 11:21:44 +02:00
src fix: des leaks si fail sur cpy env 2025-04-22 11:21:44 +02:00
.gitignore heredoc works but not with backslashs 2025-03-17 15:13:55 +01:00
.gitmodules add: libft submodule 2025-03-17 15:19:32 +01:00
.valgrindignore.txt add: base parsing 2025-03-11 14:05:52 +01:00
Makefile bcp de fix 2025-04-07 14:23:12 +02:00
README.md feat: add README.md 2026-07-01 17:01:54 +02:00

minishell

A minimalist reimplementation of a Unix shell, written in C as part of the 42 curriculum. It reproduces the core behaviour of bash in an interactive session: a read-eval-print loop, command execution with PATH resolution, pipelines, redirections, here-doc, env var expansion, quote handling and, a set of built-in commands.

The project is constrained by the 42 C Cursus coding standard (the Norminette): Using only C99, no global variables except a single one reserved for signal handling, functions limited to 25 lines, and a restricted set of allowed libc functions, etc...

Features

Interpreter

  • Interactive prompt built on GNU readline, with command history.
  • PATH lookup for executables, and direct execution of absolute and relative paths.
  • Correct propagation of exit status, exposed through $?.

Parsing

The input line goes through a small, staged pipeline:

  1. Expansion — substitutes $VAR and $?, respecting quoting rules (no expansion inside single quotes).
  2. Tokenization — splits the expanded line into raw tokens.
  3. Lexing — assigns a type to each token (command, argument, pipe, redirection, redirection target), strips quotes, and rejects invalid operators.
  4. Command building — groups tokens into a list of commands separated by pipes, resolves each command path, and opens the associated redirection targets.

Single quotes (') and double quotes (") are supported, including their different effects on expansion.

Redirections and pipes

  • Input redirection: <
  • Output redirection (truncate): >
  • Output redirection (append): >>
  • Here-document: << (with expansion unless the delimiter is quoted)
  • Pipelines of arbitrary length: cmd1 | cmd2 | cmd3 | ...

Built-in commands

Implemented as internal functions rather than external binaries:

Builtin Description
echo Print arguments, with support for the -n option
cd Change directory (absolute/relative path, ~, HOME)
pwd Print the current working directory
export Add or update environment variables; print sorted env
unset Remove environment variables
env Print the environment
exit Leave the shell with an optional status code

Signals

Signal behaviour mirrors an interactive bash session, with distinct configurations for the prompt, the execution phase, forked children and built-ins:

  • Ctrl-C (SIGINT) at the prompt clears the current line and redisplays a fresh prompt; during a running command it interrupts the child (status 130).
  • Ctrl-\ (SIGQUIT) is ignored at the prompt and default in children (status 131).
  • Ctrl-D (EOF) on an empty line exits the shell.

Per the Norm, a single global variable is used, and only to carry the last received signal number.

Architecture

src/
├── minishell.c            Entry point
├── shell/prompt.c         Read-eval-print loop and prompt rendering
├── parsing/               Expansion, tokenizer, lexer, command builder
├── commands/
│   ├── exec.c             Pipeline execution: fork, pipe, dup2, wait
│   ├── builtins/          echo, cd, pwd, export, unset, env, exit
│   └── operands/          Redirections (<, >, >>, <<) and operator checks
├── env/                   Environment access, expansion, sorting, PWD update
├── signals/               sigaction setups and handlers per execution context
├── errors/                Error reporting helpers
└── utils/                 PATH resolution, fd management, temp files
  • Hand made dynamic vector. A generic growable-array module from libft made during the cursus is used throughout: for the command list, argument lists, token lists, and even for building strings character by character during expansion. This keeps memory handling uniform and centralises cleanup.
  • Staged parsing. Each parsing stage has a single responsibility and a clear input/output contract, which makes the flow from raw line to executable command list easy to follow and to free on error.