{"id":24396313,"url":"https://github.com/mathyscogne/42_minishell","last_synced_at":"2025-08-09T00:25:36.059Z","repository":{"id":272360486,"uuid":"902521469","full_name":"MathysCogne/42_MiniShell","owner":"MathysCogne","description":"MiniShell: A custom Unix shell developed in C. Supports pipes, redirections, built-in commands (cd, echo, etc.), environment variable expansion, and error handling. ","archived":false,"fork":false,"pushed_at":"2025-01-15T17:13:06.000Z","size":2107,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-13T04:14:14.101Z","etag":null,"topics":["42","c","minishell"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MathysCogne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-12-12T18:20:31.000Z","updated_at":"2025-02-09T18:45:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"6521be7d-ee3d-418b-874b-e81c30945fab","html_url":"https://github.com/MathysCogne/42_MiniShell","commit_stats":null,"previous_names":["mathyscogne/42_minishell"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MathysCogne/42_MiniShell","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathysCogne%2F42_MiniShell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathysCogne%2F42_MiniShell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathysCogne%2F42_MiniShell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathysCogne%2F42_MiniShell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MathysCogne","download_url":"https://codeload.github.com/MathysCogne/42_MiniShell/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathysCogne%2F42_MiniShell/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260843265,"owners_count":23071518,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["42","c","minishell"],"created_at":"2025-01-19T21:26:03.890Z","updated_at":"2025-08-09T00:25:36.040Z","avatar_url":"https://github.com/MathysCogne.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"subject/cover.png\" alt=\"Covers\" width=\"650\" /\u003e\n\n\u003c/br\u003e\n\u003c/br\u003e\n\n\u003cstrong\u003eMinishell 👨‍💻🐧\u003c/strong\u003e\n\n\u003cp\u003eMinishell is a project from 42 School that involves creating a shell in C.\u003c/p\u003e\n\n\u003c/br\u003e\n\n\u003cp\u003e\u003ca href=\"https://github.com/MathysCogne/42_MiniShell/blob/main/subject/en.subject.pdf\"\u003e\u003cstrong\u003eSubject\u003c/strong\u003e\u003c/a\u003e\u003c/p\u003e\n\n\u003c/div\u003e\n\n## Features\n\n- **Prompt**: Displays a prompt when waiting for a new command.\n- **History**: Keeps a history of commands.\n- **Pipes**: Supports pipes (`|`) to connect multiple commands.\n- **Redirections**: Handles redirections (`\u003e`, `\u003e\u003e`, `\u003c`, `\u003c\u003c`) seamlessly.\n- **Environment Variables**: Expands environment variables (`$HOME`, `$PATH`, etc.).\n- **Error Codes**: Tracks and returns error codes (`$?`) for executed commands.\n- **Builtins**: Implements internal commands:\n  - `echo` (with `-n` flag)\n  - `cd` (change directory)\n  - `pwd` (print working directory)\n  - `export` (set environment variables)\n  - `unset` (unset environment variables)\n  - `env` (display environment variables)\n  - `exit` (terminate the shell)\n- **Signals**: Properly handles signals such as:\n  - `Ctrl+C` (interrupts the current command and displays a new prompt)\n  - `Ctrl+D` (exits the shell if pressed at an empty prompt)\n  - `Ctrl+\\` (ignored in interactive mode).\n\n\u003c/br\u003e\n\n## Parsing Part\n\nThe parsing stage is the backbone of the shell, as it transforms the raw input into a structured format for execution. It consists of two main steps: **tokenization** and **semantic analysis**.\n\n### Tokenization\nThe tokenization process splits the user's input into tokens, which are the smallest meaningful units of the command. These tokens include:\n\n- **Commands** (e.g., `ls`, `cat`, `grep`)\n- **Arguments** (e.g., `-l`, `file.txt`)\n- **Redirections** (`\u003e`, `\u003e\u003e`, `\u003c`, `\u003c\u003c`)\n- **Pipes** (`|`)\n\n#### How Tokenization Works:\n1. **Identify the components**: The input string is traversed character by character to identify commands, arguments, redirections, and special characters like `|`.\n2. **Handle quotes**: Properly handles single (`'`) and double (`\"`) quotes to preserve spaces or special characters inside quoted strings.\n   - Single quotes prevent all expansions.\n   - Double quotes allow variable expansions (`$`).\n3. **Ignore whitespace**: Skips unnecessary spaces while separating meaningful components.\n4. **Classify tokens**: Assigns a type to each token (e.g., `TOKEN_COMMAND`, `TOKEN_ARGUMENT`, `TOKEN_PIPE`, etc.).\n\n\u003c/br\u003e\n\nInput:\n\n```bash\necho \"hello world\" | grep hello \u003e output.txt\n```\nTokens generated:\n\n```bash\n[TOKEN_COMMAND: echo]\n[TOKEN_ARGUMENT: \"hello world\"]\n[TOKEN_PIPE: |]\n[TOKEN_COMMAND: grep]\n[TOKEN_ARGUMENT: hello]\n[TOKEN_REDIRECTION_OUT: \u003e]\n[TOKEN_ARGUMENT: output.txt]\n```\n\n\u003c/br\u003e\n\n### **2. Semantic Analysis**\n\nThe semantic analysis phase transforms the list of tokens into a hierarchy of commands and redirections while validating the syntax. This ensures that the input is both logical and executable.\n\n#### Steps of Semantic Analysis:\n1. **Validate Syntax**:\n   - Detect invalid sequences like `| |`, `; ;`, or missing arguments for redirections (`\u003e`, `\u003c`).\n   - Example: `echo |` will raise an error.\n2. **Group Tokens**:\n   - Constructs a command tree where each node represents a command or redirection.\n   - Associates redirections (`\u003e`, `\u003c`, etc.) with their respective commands.\n3. **Handle Logical Constructs**:\n   - Maps pipes (`|`) to connect commands in a pipeline.\n\n\u003c/br\u003e\n\nInput:\n\n```bash\ncat file.txt | grep \"hello\" \u003e result.txt\n```\nCommand structure:\n\n```yaml\nCommand 1:\n  - Executable: cat\n  - Arguments: [file.txt]\n\nPipe to Command 2:\nCommand 2:\n  - Executable: grep\n  - Arguments: [\"hello\"]\n  - Redirection: \u003e result.txt\n```\n\n\u003c/br\u003e\n\n\n## Execution Part\n\nOnce the input is parsed and analyzed, the shell proceeds to the execution phase. Commands are executed in separate processes, with builtins handled directly in the shell process.\n\n### Execution Flow:\n1. **Forking**:\n   - Creates a new process using `fork()` for each external command.\n   - The parent process waits for the child process to complete using `waitpid()`.\n2. **Piping**:\n   - Sets up pipes (`pipe()`) to connect the output of one command to the input of the next.\n   - Uses `dup2()` to duplicate file descriptors for standard input/output redirection.\n3. **Redirections**:\n   - Opens file descriptors for input/output redirections (`\u003c`, `\u003e`, `\u003e\u003e`, `\u003c\u003c`).\n   - Uses `dup2()` to redirect standard input/output to the appropriate file descriptors.\n4. **Builtin Commands**:\n   - Executes builtins directly without forking to avoid unnecessary processes.\n   - Builtins are handled by specific functions within the shell process.\n\n\n\u003c/br\u003e\n\n## Compilation and Usage\n\n\u003c/br\u003e\n\n```bash\n# Compile:\nmake\n\n# Start shell:\n./minishell\n\n# Start shell with test (Norm and Valgrind):\nmake test\n```\n\n\u003c/br\u003e\n\n\n⊹ ࣪ ﹏𓊝﹏𓂁﹏⊹ ࣪ ˖\n\n\u003c/br\u003e\n\n## Disclaimer\n\u003e At 42 School, most projects must comply with the [Norm](https://github.com/42School/norminette/blob/master/pdf/en.norm.pdf).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathyscogne%2F42_minishell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathyscogne%2F42_minishell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathyscogne%2F42_minishell/lists"}